Skip to content

Commit

Permalink
Add sparse color attachment cases to sample_mask alphaToCoverage test
Browse files Browse the repository at this point in the history
  • Loading branch information
shrekshao committed Mar 9, 2023
1 parent 0e32299 commit 73fb11a
Showing 1 changed file with 79 additions and 48 deletions.
127 changes: 79 additions & 48 deletions src/webgpu/api/operation/render_pipeline/sample_mask.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ class F extends TextureTestMixin(GPUTest) {
rasterizationMask: number,
pipeline: GPURenderPipeline,
uniformBuffer: GPUBuffer,
colorTargetsCount: number = 1
): { color: GPUTexture; depthStencil: GPUTexture } {
colorTargets: Iterable<GPUColorTargetState | null>
): { colors: (GPUTexture | null)[]; depthStencil: GPUTexture } {
assert(this.sampleTexture !== undefined);
assert(this.sampler !== undefined);

Expand All @@ -286,37 +286,42 @@ class F extends TextureTestMixin(GPUTest) {
],
});

const renderTargetTextures = [];
const renderTargetTextures: (GPUTexture | null)[] = [];
const resolveTargetTextures: (GPUTexture | null)[] = [];
for (let i = 0; i < colorTargetsCount; i++) {
const renderTargetTexture = this.device.createTexture({
format,
size: {
width: kRenderTargetSize,
height: kRenderTargetSize,
depthOrArrayLayers: 1,
},
sampleCount,
mipLevelCount: 1,
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
});
renderTargetTextures.push(renderTargetTexture);

const resolveTargetTexture =
sampleCount === 1
? null
: this.device.createTexture({
format,
size: {
width: kRenderTargetSize,
height: kRenderTargetSize,
depthOrArrayLayers: 1,
},
sampleCount: 1,
mipLevelCount: 1,
usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
});
resolveTargetTextures.push(resolveTargetTexture);
for (const target of colorTargets) {
if (target === null) {
renderTargetTextures.push(null);
resolveTargetTextures.push(null);
} else {
const renderTargetTexture = this.device.createTexture({
format,
size: {
width: kRenderTargetSize,
height: kRenderTargetSize,
depthOrArrayLayers: 1,
},
sampleCount,
mipLevelCount: 1,
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
});
renderTargetTextures.push(renderTargetTexture);

const resolveTargetTexture =
sampleCount === 1
? null
: this.device.createTexture({
format,
size: {
width: kRenderTargetSize,
height: kRenderTargetSize,
depthOrArrayLayers: 1,
},
sampleCount: 1,
mipLevelCount: 1,
usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.RENDER_ATTACHMENT,
});
resolveTargetTextures.push(resolveTargetTexture);
}
}

const depthStencilTexture = this.device.createTexture({
Expand All @@ -331,6 +336,10 @@ class F extends TextureTestMixin(GPUTest) {

const renderPassDescriptor: GPURenderPassDescriptor = {
colorAttachments: renderTargetTextures.map((renderTargetTexture, index) => {
if (renderTargetTexture === null) {
return null;
}

return {
view: renderTargetTexture.createView(),
resolveTarget: resolveTargetTextures[index]?.createView(),
Expand Down Expand Up @@ -383,7 +392,7 @@ class F extends TextureTestMixin(GPUTest) {
this.device.queue.submit([commandEncoder.finish()]);

return {
color: renderTargetTextures[0],
colors: renderTargetTextures,
depthStencil: depthStencilTexture,
};
}
Expand Down Expand Up @@ -514,6 +523,7 @@ textureLoad each sample index from the texture and write to a storage buffer to
new Uint32Array([fragmentShaderOutputMask])
);

const colorTargets = [{ format }] as const;
const pipeline = t.device.createRenderPipeline({
layout: 'auto',
vertex: {
Expand All @@ -540,7 +550,7 @@ textureLoad each sample index from the texture and write to a storage buffer to
}`,
}),
entryPoint: 'main',
targets: [{ format }],
targets: colorTargets,
},
primitive: { topology: 'triangle-list' },
multisample: {
Expand All @@ -564,12 +574,15 @@ textureLoad each sample index from the texture and write to a storage buffer to
},
});

const { color, depthStencil } = t.GetTargetTexture(
const { colors, depthStencil } = t.GetTargetTexture(
sampleCount,
rasterizationMask,
pipeline,
fragmentMaskUniformBuffer
fragmentMaskUniformBuffer,
colorTargets
);
const color = colors[0];
assert(color !== null);

t.CheckColorAttachmentResult(
color,
Expand Down Expand Up @@ -601,12 +614,13 @@ textureLoad each sample index from the texture and write to a storage buffer to
g.test('alpha_to_coverage_mask')
.desc(
`
Test that alpha_to_coverage_mask is working properly with the alpha output of color target[0].
Test that alpha_to_coverage_mask is working properly with the shader alpha output of color target[0].
- for sampleCount = 4, alphaToCoverageEnabled = true and various combinations of:
- rasterization masks
- increasing alpha0 values of the color0 output including { < 0, = 0, = 1/16, = 2/16, ..., = 15/16, = 1, > 1 }
- alpha1 values of the color1 output = { 0, 0.5, 1.0 }.
- unrelated alpha1 values of the color1 output = { 0, 0.5, 1.0 } (when target[0] is not empty) or = { 1.0 } (when target[0] is empty)
- target[0] is empty or not
- test that for a single pixel in { color0, color1 } { color0, depth, stencil } output the final sample mask is applied to it, moreover:
- if alpha0 is 0.0 or less then alpha to coverage mask is 0x0,
- if alpha0 is 1.0 or greater then alpha to coverage mask is 0xFFFFFFFF,
Expand All @@ -622,18 +636,31 @@ color' <= color.
)
.params(u =>
u
.combine('hasSparseColorAttachment', [false, true] as const)
.expand('rasterizationMask', function* (p) {
for (let i = 0, len = 0xf; i <= len; i++) {
yield i;
}
})
.beginSubcases()
.combine('alpha1', [0.0, 0.5, 1.0] as const)
.expand('alpha1', p => {
if (p.hasSparseColorAttachment) {
// when hasSparseColorAttachment is true
// target[0] is empty but target[0].a is still used as alphaToCoverage value.
// target[1] is used as the color output, so target[1].a stays at 1.0 to match sample texture values.
return [1.0];
}
return [0.0, 0.5, 1.0];
})
)
.fn(async t => {
const sampleCount = 4;
const sampleMask = 0xffffffff;
const { rasterizationMask, alpha1 } = t.params;
const { hasSparseColorAttachment, rasterizationMask, alpha1 } = t.params;
const colorTargets = [
hasSparseColorAttachment ? null : ({ format } as const),
{ format },
] as const;

const alphaValues = new Float32Array(4); // [alpha0, alpha1, 0, 0]
const alphaValueUniformBuffer = t.device.createBuffer({
Expand Down Expand Up @@ -674,7 +701,7 @@ color' <= color.
}`,
}),
entryPoint: 'main',
targets: [{ format }, { format }],
targets: colorTargets,
},
primitive: { topology: 'triangle-list' },
multisample: {
Expand All @@ -699,25 +726,29 @@ color' <= color.
});

// { < 0, = 0, = 1/16, = 2/16, ..., = 15/16, = 1, > 1 }
const alpha0ParamsArray = [-0.1, ...range(16, i => i / 16), 1.0, 1.1];
const alphaParamsArray = [-0.1, ...range(16, i => i / 16), 1.0, 1.1];

const colorResultPromises = [];
const depthResultPromises = [];
const stencilResultPromises = [];

for (const alpha0 of alpha0ParamsArray) {
for (const alpha0 of alphaParamsArray) {
alphaValues[0] = alpha0;
alphaValues[1] = alpha1;

t.device.queue.writeBuffer(alphaValueUniformBuffer, 0, alphaValues);

const { color, depthStencil } = t.GetTargetTexture(
const { colors, depthStencil } = t.GetTargetTexture(
sampleCount,
rasterizationMask,
pipeline,
alphaValueUniformBuffer,
2
colorTargets
);

const color = hasSparseColorAttachment ? colors[1] : colors[0];
assert(color !== null);

const colorBuffer = t.copySinglePixelTextureToBufferUsingComputePass(
TypeF32, // correspond to 'rgba8unorm' format
4,
Expand Down Expand Up @@ -776,13 +807,13 @@ color' <= color.
) => {
for (let i = 0; i < results.length; i++) {
const result = results[i];
const alpha0 = alpha0ParamsArray[i];
const alpha = alphaParamsArray[i];

if (alpha0 <= 0) {
if (alpha <= 0) {
const expected = getExpectedDataFn(sampleCount, rasterizationMask, sampleMask, 0x0);
const check = checkElementsEqual(result.data, expected);
t.expectOK(check);
} else if (alpha0 >= 1) {
} else if (alpha >= 1) {
const expected = getExpectedDataFn(
sampleCount,
rasterizationMask,
Expand Down

0 comments on commit 73fb11a

Please sign in to comment.