Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

val: Add depthSlice tests to render_pass_descriptor:color_attachments #3238

Merged
merged 6 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 182 additions & 0 deletions src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class F extends ValidationTest {
createTexture(
options: {
format?: GPUTextureFormat;
dimension?: GPUTextureDimension;
width?: number;
height?: number;
arrayLayerCount?: number;
Expand All @@ -30,6 +31,7 @@ class F extends ValidationTest {
): GPUTexture {
const {
format = 'rgba8unorm',
dimension = '2d',
width = 16,
height = 16,
arrayLayerCount = 1,
Expand All @@ -41,6 +43,7 @@ class F extends ValidationTest {
return this.device.createTexture({
size: { width, height, depthOrArrayLayers: arrayLayerCount },
format,
dimension,
mipLevelCount,
sampleCount,
usage,
Expand Down Expand Up @@ -90,6 +93,7 @@ class F extends ValidationTest {
}

export const g = makeTestGroup(F);
const kArrayLayerCount = 10;

g.test('attachments,one_color_attachment')
.desc(`Test that a render pass works with only one color attachment.`)
Expand Down Expand Up @@ -278,6 +282,184 @@ g.test('color_attachments,limits,maxColorAttachmentBytesPerSample,unaligned')
t.tryRenderPass(success, { colorAttachments });
});

g.test('color_attachments,depthSlice,definedness')
.desc(
`
Test that depthSlice must be undefined for 2d color attachments and defined for 3d color attachments."
- The special value '0xFFFFFFFF' is not treated as 'undefined'.
`
)
.params(u =>
u
.combine('dimension', ['2d', '3d'] as GPUTextureDimension[])
.beginSubcases()
.combine('depthSlice', [undefined, 0, 0xffffffff])
)
.fn(t => {
const { dimension, depthSlice } = t.params;
const texture = t.createTexture({ dimension });

const colorAttachment = t.getColorAttachment(texture);
if (depthSlice !== undefined) {
colorAttachment.depthSlice = depthSlice;
}

const descriptor: GPURenderPassDescriptor = {
colorAttachments: [colorAttachment],
};

const success =
(dimension === '2d' && depthSlice === undefined) || (dimension === '3d' && depthSlice === 0);

t.tryRenderPass(success, descriptor);
});

g.test('color_attachments,depthSlice,bound_check')
.desc(
`
Test that depthSlice must be less than the depthOrArrayLayers of 3d texture's subresource at mip levels.
- Check depth bounds with 3d texture size [16, 1, 10], which has 5 mip levels with depth [10, 5, 2, 1, 1]
for testing more mip level size computation.
- Failed if depthSlice >= the depth of each mip level.
`
)
.params(u =>
u
.combine('mipLevel', [0, 1, 2, 3, 4])
.beginSubcases()
.expand('depthSlice', ({ mipLevel }) => {
const depthAtMipLevel = Math.max(kArrayLayerCount >> mipLevel, 1);
// Use Set() to exclude duplicates when the depthAtMipLevel is 1 and 2
return [...new Set([0, 1, depthAtMipLevel - 1, depthAtMipLevel])];
})
)
.fn(t => {
const { mipLevel, depthSlice } = t.params;

const texture = t.createTexture({
dimension: '3d',
width: 16,
height: 1,
arrayLayerCount: kArrayLayerCount,
mipLevelCount: mipLevel + 1,
});

const viewDescriptor: GPUTextureViewDescriptor = {
baseMipLevel: mipLevel,
mipLevelCount: 1,
baseArrayLayer: 0,
arrayLayerCount: 1,
};

const colorAttachment = t.getColorAttachment(texture, viewDescriptor);
colorAttachment.depthSlice = depthSlice;

const passDescriptor: GPURenderPassDescriptor = {
colorAttachments: [colorAttachment],
};

const success = depthSlice < Math.max(kArrayLayerCount >> mipLevel, 1);

t.tryRenderPass(success, passDescriptor);
});

g.test('color_attachments,depthSlice,overlaps,same_miplevel')
.desc(
`
Test that the depth slices of 3d color attachments have no overlaps for same texture in a render
pass.
- Succeed if the depth slices are different, or from different textures, or on different render
passes.
- Fail if same depth slice from same texture's same mip level is overwritten in a render pass.
`
)
.params(u =>
u
.combine('sameDepthSlice', [true, false])
.beginSubcases()
.combine('sameTexture', [true, false])
.combine('samePass', [true, false])
)
.fn(t => {
const { sameDepthSlice, sameTexture, samePass } = t.params;
const arrayLayerCount = 4;

const texDescriptor = {
dimension: '3d' as GPUTextureDimension,
arrayLayerCount,
};
const texture = t.createTexture(texDescriptor);

const colorAttachments = [];
for (let i = 0; i < arrayLayerCount; i++) {
const colorAttachment = t.getColorAttachment(
sameTexture ? texture : t.createTexture(texDescriptor)
);
colorAttachment.depthSlice = sameDepthSlice ? 0 : i;
colorAttachments.push(colorAttachment);
}

const encoder = t.createEncoder('non-pass');
if (samePass) {
const pass = encoder.encoder.beginRenderPass({ colorAttachments });
pass.end();
} else {
for (let i = 0; i < arrayLayerCount; i++) {
const pass = encoder.encoder.beginRenderPass({ colorAttachments: [colorAttachments[i]] });
pass.end();
}
}

const success = !sameDepthSlice || !sameTexture || !samePass;

encoder.validateFinish(success);
});

g.test('color_attachments,depthSlice,overlaps,diff_miplevel')
.desc(
`
Test that the same depth slice from different mip levels of a 3d texture with size [1, 1, N] can
be set in a render pass's color attachments.
`
)
.params(u => u.combine('sameMipLevel', [true, false]))
.fn(t => {
const { sameMipLevel } = t.params;
const mipLevelCount = 4;

const texDescriptor = {
dimension: '3d' as GPUTextureDimension,
width: 1,
height: 1,
arrayLayerCount: 1 << mipLevelCount,
mipLevelCount,
};
const texture = t.createTexture(texDescriptor);

const viewDescriptor: GPUTextureViewDescriptor = {
baseMipLevel: 0,
mipLevelCount: 1,
baseArrayLayer: 0,
arrayLayerCount: 1,
};

const colorAttachments = [];
for (let i = 0; i < mipLevelCount; i++) {
if (!sameMipLevel) {
viewDescriptor.baseMipLevel = i;
}
const colorAttachment = t.getColorAttachment(texture, viewDescriptor);
colorAttachment.depthSlice = 0;
colorAttachments.push(colorAttachment);
}

const encoder = t.createEncoder('non-pass');
const pass = encoder.encoder.beginRenderPass({ colorAttachments });
pass.end();

encoder.validateFinish(!sameMipLevel);
});

g.test('attachments,same_size')
.desc(
`
Expand Down
4 changes: 4 additions & 0 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,10 @@
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,empty:*": { "subcaseMS": 0.400 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachmentBytesPerSample,aligned:*": { "subcaseMS": 1.825 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachmentBytesPerSample,unaligned:*": { "subcaseMS": 17.151 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,definedness:*": { "subcaseMS": 5.601 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,bound_check:*": { "subcaseMS": 9.400 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,overlaps,same_miplevel:*": { "subcaseMS": 6.400 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,depthSlice,overlaps,diff_miplevel:*": { "subcaseMS": 3.901 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,limits,maxColorAttachments:*": { "subcaseMS": 0.950 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,non_multisampled:*": { "subcaseMS": 32.601 },
"webgpu:api,validation,render_pass,render_pass_descriptor:color_attachments,sample_count:*": { "subcaseMS": 33.600 },
Expand Down