summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.ts203
1 files changed, 203 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.ts
new file mode 100644
index 0000000000..e242ed8114
--- /dev/null
+++ b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/render_pipeline/depth_stencil_state.spec.ts
@@ -0,0 +1,203 @@
+export const description = `
+This test dedicatedly tests validation of GPUDepthStencilState of createRenderPipeline.
+`;
+
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { unreachable } from '../../../../common/util/util.js';
+import {
+ kTextureFormats,
+ kTextureFormatInfo,
+ kDepthStencilFormats,
+ kCompareFunctions,
+ kStencilOperations,
+} from '../../../capability_info.js';
+import { getFragmentShaderCodeWithOutput } from '../../../util/shader.js';
+
+import { CreateRenderPipelineValidationTest } from './common.js';
+
+export const g = makeTestGroup(CreateRenderPipelineValidationTest);
+
+g.test('format')
+ .desc(`The texture format in depthStencilState must be a depth/stencil format.`)
+ .params(u => u.combine('isAsync', [false, true]).combine('format', kTextureFormats))
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({ depthStencil: { format } });
+
+ t.doCreateRenderPipelineTest(isAsync, info.depth || info.stencil, descriptor);
+ });
+
+g.test('depth_test')
+ .desc(
+ `Depth aspect must be contained in the format if depth test is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('depthCompare', [undefined, ...kCompareFunctions])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, depthCompare } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({
+ depthStencil: { format, depthCompare },
+ });
+
+ const depthTestEnabled = depthCompare !== undefined && depthCompare !== 'always';
+ t.doCreateRenderPipelineTest(isAsync, !depthTestEnabled || info.depth, descriptor);
+ });
+
+g.test('depth_write')
+ .desc(
+ `Depth aspect must be contained in the format if depth write is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('depthWriteEnabled', [false, true])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, depthWriteEnabled } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ const descriptor = t.getDescriptor({
+ depthStencil: { format, depthWriteEnabled },
+ });
+ t.doCreateRenderPipelineTest(isAsync, !depthWriteEnabled || info.depth, descriptor);
+ });
+
+g.test('depth_write,frag_depth')
+ .desc(`Depth aspect must be contained in the format if frag_depth is written in fragment stage.`)
+ .params(u =>
+ u.combine('isAsync', [false, true]).combine('format', [undefined, ...kDepthStencilFormats])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ if (format !== undefined) {
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ }
+ })
+ .fn(async t => {
+ const { isAsync, format } = t.params;
+
+ const descriptor = t.getDescriptor({
+ // Keep one color target so that the pipeline is still valid with no depth stencil target.
+ targets: [{ format: 'rgba8unorm' }],
+ depthStencil: format ? { format, depthWriteEnabled: true } : undefined,
+ fragmentShaderCode: getFragmentShaderCodeWithOutput(
+ [{ values: [1, 1, 1, 1], plainType: 'f32', componentCount: 4 }],
+ { value: 0.5 }
+ ),
+ });
+
+ const hasDepth = format ? kTextureFormatInfo[format].depth : false;
+ t.doCreateRenderPipelineTest(isAsync, hasDepth, descriptor);
+ });
+
+g.test('stencil_test')
+ .desc(
+ `Stencil aspect must be contained in the format if stencil test is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('face', ['front', 'back'] as const)
+ .combine('compare', [undefined, ...kCompareFunctions])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, face, compare } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ let descriptor: GPURenderPipelineDescriptor;
+ if (face === 'front') {
+ descriptor = t.getDescriptor({ depthStencil: { format, stencilFront: { compare } } });
+ } else {
+ descriptor = t.getDescriptor({ depthStencil: { format, stencilBack: { compare } } });
+ }
+
+ const stencilTestEnabled = compare !== undefined && compare !== 'always';
+ t.doCreateRenderPipelineTest(isAsync, !stencilTestEnabled || info.stencil, descriptor);
+ });
+
+g.test('stencil_write')
+ .desc(
+ `Stencil aspect must be contained in the format if stencil write is enabled in depthStencilState.`
+ )
+ .params(u =>
+ u
+ .combine('isAsync', [false, true])
+ .combine('format', kDepthStencilFormats)
+ .combine('faceAndOpType', [
+ 'frontFailOp',
+ 'frontDepthFailOp',
+ 'frontPassOp',
+ 'backFailOp',
+ 'backDepthFailOp',
+ 'backPassOp',
+ ] as const)
+ .combine('op', [undefined, ...kStencilOperations])
+ )
+ .beforeAllSubcases(t => {
+ const { format } = t.params;
+ const info = kTextureFormatInfo[format];
+ t.selectDeviceOrSkipTestCase(info.feature);
+ })
+ .fn(async t => {
+ const { isAsync, format, faceAndOpType, op } = t.params;
+ const info = kTextureFormatInfo[format];
+
+ let depthStencil: GPUDepthStencilState;
+ switch (faceAndOpType) {
+ case 'frontFailOp':
+ depthStencil = { format, stencilFront: { failOp: op } };
+ break;
+ case 'frontDepthFailOp':
+ depthStencil = { format, stencilFront: { depthFailOp: op } };
+ break;
+ case 'frontPassOp':
+ depthStencil = { format, stencilFront: { passOp: op } };
+ break;
+ case 'backFailOp':
+ depthStencil = { format, stencilBack: { failOp: op } };
+ break;
+ case 'backDepthFailOp':
+ depthStencil = { format, stencilBack: { depthFailOp: op } };
+ break;
+ case 'backPassOp':
+ depthStencil = { format, stencilBack: { passOp: op } };
+ break;
+ default:
+ unreachable();
+ }
+ const descriptor = t.getDescriptor({ depthStencil });
+
+ const stencilWriteEnabled = op !== undefined && op !== 'keep';
+ t.doCreateRenderPipelineTest(isAsync, !stencilWriteEnabled || info.stencil, descriptor);
+ });