blob: 5da8a5c21b60d7951ea24ca7332f0914bb3fb385 [file] [log] [blame]
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ export const description = `API Operation Tests for RenderPass StoreOp.
Tests a render pass with a resolveTarget resolves correctly for many combinations of:
- number of color attachments, some with and some without a resolveTarget
- renderPass storeOp set to {'store', 'clear'}
- resolveTarget mip level {0, >0} (TODO?: different mip level from colorAttachment)
- resolveTarget {2d array layer, TODO: 3d slice} {0, >0} with {2d, TODO: 3d} resolveTarget
(TODO?: different z from colorAttachment)
- TODO: test all renderable color formats
- TODO: test that any not-resolved attachments are rendered to correctly.
- TODO: test different loadOps
- TODO?: resolveTarget mip level {0, >0} (TODO?: different mip level from colorAttachment)
- TODO?: resolveTarget {2d array layer, TODO: 3d slice} {0, >0} with {2d, TODO: 3d} resolveTarget
(different z from colorAttachment)
`;
import { params, poptions } from '../../../../common/framework/params_builder.js';
import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { GPUTest } from '../../../gpu_test.js';
const kSlotsToResolve = [
[0, 2],
[1, 3],
[0, 1, 2, 3],
];
const kSize = 4;
const kFormat = 'rgba8unorm';
export const g = makeTestGroup(GPUTest);
g.test('render_pass_resolve')
.params(
params()
.combine(poptions('numColorAttachments', [2, 4]))
.combine(poptions('slotsToResolve', kSlotsToResolve))
.combine(poptions('storeOperation', ['clear', 'store']))
.combine(poptions('resolveTargetBaseMipLevel', [0, 1]))
.combine(poptions('resolveTargetBaseArrayLayer', [0, 1]))
)
.fn(t => {
const colorStateDescriptors = [];
for (let i = 0; i < t.params.numColorAttachments; i++) {
colorStateDescriptors.push({ format: kFormat });
}
// These shaders will draw a white triangle into a texture. After draw, the top left
// half of the texture will be white, and the bottom right half will be unchanged. When this
// texture is resolved, there will be two distinct colors in each portion of the texture, as
// well as a line between the portions that contain the midpoint color due to the multisample
// resolve.
const pipeline = t.device.createRenderPipeline({
vertexStage: {
module: t.device.createShaderModule({
code: `
[[builtin(position)]] var<out> Position : vec4<f32>;
[[builtin(vertex_idx)]] var<in> VertexIndex : i32;
[[stage(vertex)]] fn main() -> void {
const pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
vec2<f32>(-1.0, -1.0),
vec2<f32>(-1.0, 1.0),
vec2<f32>( 1.0, 1.0));
Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
return;
}`,
}),
entryPoint: 'main',
},
fragmentStage: {
module: t.device.createShaderModule({
code: `
[[location(0)]] var<out> fragColor0 : vec4<f32>;
[[location(1)]] var<out> fragColor1 : vec4<f32>;
[[location(2)]] var<out> fragColor2 : vec4<f32>;
[[location(3)]] var<out> fragColor3 : vec4<f32>;
[[stage(fragment)]] fn main() -> void {
fragColor0 = vec4<f32>(1.0, 1.0, 1.0, 1.0);
fragColor1 = vec4<f32>(1.0, 1.0, 1.0, 1.0);
fragColor2 = vec4<f32>(1.0, 1.0, 1.0, 1.0);
fragColor3 = vec4<f32>(1.0, 1.0, 1.0, 1.0);
return;
}`,
}),
entryPoint: 'main',
},
primitiveTopology: 'triangle-list',
colorStates: colorStateDescriptors,
sampleCount: 4,
});
const resolveTargets = [];
const renderPassColorAttachmentDescriptors = [];
// The resolve target must be the same size as the color attachment. If we're resolving to mip
// level 1, the resolve target base mip level should be 2x the color attachment size.
const kResolveTargetSize = kSize << t.params.resolveTargetBaseMipLevel;
for (let i = 0; i < t.params.numColorAttachments; i++) {
const colorAttachment = t.device.createTexture({
format: kFormat,
size: { width: kSize, height: kSize, depth: 1 },
sampleCount: 4,
mipLevelCount: 1,
usage:
GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT,
});
if (t.params.slotsToResolve.includes(i)) {
const colorAttachment = t.device.createTexture({
format: kFormat,
size: { width: kSize, height: kSize, depth: 1 },
sampleCount: 4,
mipLevelCount: 1,
usage:
GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT,
});
const resolveTarget = t.device.createTexture({
format: kFormat,
size: {
width: kResolveTargetSize,
height: kResolveTargetSize,
depth: t.params.resolveTargetBaseArrayLayer + 1,
},
sampleCount: 1,
mipLevelCount: t.params.resolveTargetBaseMipLevel + 1,
usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.OUTPUT_ATTACHMENT,
});
// Clear to black for the load operation. After the draw, the top left half of the attachment
// will be white and the bottom right half will be black.
renderPassColorAttachmentDescriptors.push({
attachment: colorAttachment.createView(),
loadValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
storeOp: t.params.storeOperation,
resolveTarget: resolveTarget.createView({
baseMipLevel: t.params.resolveTargetBaseMipLevel,
baseArrayLayer: t.params.resolveTargetBaseArrayLayer,
}),
});
resolveTargets.push(resolveTarget);
} else {
renderPassColorAttachmentDescriptors.push({
attachment: colorAttachment.createView(),
loadValue: { r: 0.0, g: 0.0, b: 0.0, a: 0.0 },
storeOp: t.params.storeOperation,
});
}
}
const encoder = t.device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: renderPassColorAttachmentDescriptors,
});
pass.setPipeline(pipeline);
pass.draw(3);
pass.endPass();
t.device.defaultQueue.submit([encoder.finish()]);
// Verify the resolve targets contain the correct values.
for (let i = 0; i < resolveTargets.length; i++) {
// Test top left pixel, which should be {255, 255, 255, 255}.
t.expectSinglePixelIn2DTexture(
resolveTargets[i],
kFormat,
{ x: 0, y: 0 },
{
exp: new Uint8Array([0xff, 0xff, 0xff, 0xff]),
slice: t.params.resolveTargetBaseArrayLayer,
layout: { mipLevel: t.params.resolveTargetBaseMipLevel },
}
);
// Test bottom right pixel, which should be {0, 0, 0, 0}.
t.expectSinglePixelIn2DTexture(
resolveTargets[i],
kFormat,
{ x: kSize - 1, y: kSize - 1 },
{
exp: new Uint8Array([0x00, 0x00, 0x00, 0x00]),
slice: t.params.resolveTargetBaseArrayLayer,
layout: { mipLevel: t.params.resolveTargetBaseMipLevel },
}
);
// Test top right pixel, which should be {127, 127, 127, 127} due to the multisampled resolve.
t.expectSinglePixelIn2DTexture(
resolveTargets[i],
kFormat,
{ x: kSize - 1, y: 0 },
{
exp: new Uint8Array([0x7f, 0x7f, 0x7f, 0x7f]),
slice: t.params.resolveTargetBaseArrayLayer,
layout: { mipLevel: t.params.resolveTargetBaseMipLevel },
}
);
}
});