summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/decl/context_dependent_resolution.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/decl/context_dependent_resolution.spec.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/decl/context_dependent_resolution.spec.ts338
1 files changed, 338 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/decl/context_dependent_resolution.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/decl/context_dependent_resolution.spec.ts
new file mode 100644
index 0000000000..aedef043cd
--- /dev/null
+++ b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/decl/context_dependent_resolution.spec.ts
@@ -0,0 +1,338 @@
+export const description = `
+Tests that context dependent names do not participate in name resolution.
+That is, a declaration named the same as a context dependent name will not interfere.
+
+Context-dependent names:
+ * Attribute names
+ * Built-in value names
+ * Diagnostic severity control
+ * Diagnostic triggering rules
+ * Enable extensions
+ * Language extensions
+ * Swizzles
+ * Interpolation type
+ * Interpolation sampling
+`;
+
+import { makeTestGroup } from '../../../../common/framework/test_group.js';
+import { keysOf } from '../../../../common/util/data_tables.js';
+import { ShaderValidationTest } from '../shader_validation_test.js';
+
+export const g = makeTestGroup(ShaderValidationTest);
+
+const kAttributeCases = {
+ align: `struct S { @align(16) x : u32 }`,
+ binding: `@group(0) @binding(0) var s : sampler;`,
+ builtin: `@vertex fn main() -> @builtin(position) vec4f { return vec4f(); }`,
+ // const is not writable
+ // diagnostic is a keyword
+ group: `@group(0) @binding(0) var s : sampler;`,
+ id: `@id(1) override x : i32;`,
+ interpolate: `@fragment fn main(@location(0) @interpolate(flat) x : i32) { }`,
+ invariant: `@fragment fn main(@builtin(position) @invariant pos : vec4f) { }`,
+ location: `@fragment fn main(@location(0) x : f32) { }`,
+ must_use: `@must_use fn foo() -> u32 { return 0; }`,
+ size: `struct S { @size(4) x : u32 }`,
+ workgroup_size: `@compute @workgroup_size(1) fn main() { }`,
+ compute: `@compute @workgroup_size(1) fn main() { }`,
+ fragment: `@fragment fn main() { }`,
+ vertex: `@vertex fn main() -> @builtin(position) vec4f { return vec4f(); }`,
+};
+
+g.test('attribute_names')
+ .desc('Tests attribute names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', keysOf(kAttributeCases))
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ const code = `
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ ${kAttributeCases[t.params.case]}
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });
+
+const kBuiltinCases = {
+ vertex_index: `
+ @vertex
+ fn main(@builtin(vertex_index) idx : u32) -> @builtin(position) vec4f
+ { return vec4f(); }`,
+ instance_index: `
+ @vertex
+ fn main(@builtin(instance_index) idx : u32) -> @builtin(position) vec4f
+ { return vec4f(); }`,
+ position_vertex: `
+ @vertex fn main() -> @builtin(position) vec4f
+ { return vec4f(); }`,
+ position_fragment: `@fragment fn main(@builtin(position) pos : vec4f) { }`,
+ front_facing: `@fragment fn main(@builtin(front_facing) x : bool) { }`,
+ frag_depth: `@fragment fn main() -> @builtin(frag_depth) f32 { return 0; }`,
+ sample_index: `@fragment fn main(@builtin(sample_index) x : u32) { }`,
+ sample_mask_input: `@fragment fn main(@builtin(sample_mask) x : u32) { }`,
+ sample_mask_output: `@fragment fn main() -> @builtin(sample_mask) u32 { return 0; }`,
+ local_invocation_id: `
+ @compute @workgroup_size(1)
+ fn main(@builtin(local_invocation_id) id : vec3u) { }`,
+ local_invocation_index: `
+ @compute @workgroup_size(1)
+ fn main(@builtin(local_invocation_index) id : u32) { }`,
+ global_invocation_id: `
+ @compute @workgroup_size(1)
+ fn main(@builtin(global_invocation_id) id : vec3u) { }`,
+ workgroup_id: `
+ @compute @workgroup_size(1)
+ fn main(@builtin(workgroup_id) id : vec3u) { }`,
+ num_workgroups: `
+ @compute @workgroup_size(1)
+ fn main(@builtin(num_workgroups) id : vec3u) { }`,
+};
+
+g.test('builtin_value_names')
+ .desc('Tests builtin value names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', keysOf(kBuiltinCases))
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ const code = `
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ ${kBuiltinCases[t.params.case]}
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });
+
+const kDiagnosticSeverityCases = {
+ error: `
+ diagnostic(error, derivative_uniformity);
+ @diagnostic(error, derivative_uniformity) fn foo() { }
+ `,
+ warning: `
+ diagnostic(warning, derivative_uniformity);
+ @diagnostic(warning, derivative_uniformity) fn foo() { }
+ `,
+ off: `
+ diagnostic(off, derivative_uniformity);
+ @diagnostic(off, derivative_uniformity) fn foo() { }
+ `,
+ info: `
+ diagnostic(info, derivative_uniformity);
+ @diagnostic(info, derivative_uniformity) fn foo() { }
+ `,
+};
+
+g.test('diagnostic_severity_names')
+ .desc('Tests diagnostic severity names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', keysOf(kDiagnosticSeverityCases))
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ const code = `
+ ${kDiagnosticSeverityCases[t.params.case]}
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });
+
+const kDiagnosticRuleCases = {
+ derivative_uniformity: `
+ diagnostic(off, derivative_uniformity);
+ @diagnostic(warning, derivative_uniformity) fn foo() { }`,
+ unknown_rule: `
+ diagnostic(off, unknown_rule);
+ @diagnostic(warning, unknown_rule) fn foo() { }`,
+ unknown: `
+ diagnostic(off, unknown.rule);
+ @diagnostic(warning, unknown.rule) fn foo() { }`,
+ rule: `
+ diagnostic(off, unknown.rule);
+ @diagnostic(warning, unknown.rule) fn foo() { }`,
+};
+
+g.test('diagnostic_rule_names')
+ .desc('Tests diagnostic rule names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', keysOf(kDiagnosticRuleCases))
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ const code = `
+ ${kDiagnosticRuleCases[t.params.case]}
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });
+
+const kEnableCases = {
+ f16: `enable f16;`,
+};
+
+g.test('enable_names')
+ .desc('Tests enable extension names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', keysOf(kEnableCases))
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .beforeAllSubcases(t => {
+ t.selectDeviceOrSkipTestCase('shader-f16');
+ })
+ .fn(t => {
+ const code = `
+ ${kEnableCases[t.params.case]}
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });
+
+const kLanguageCases = {
+ readonly_and_readwrite_storage_textures: `requires readonly_and_readwrite_storage_textures;`,
+ packed_4x8_integer_dot_product: `requires packed_4x8_integer_dot_product;`,
+ unrestricted_pointer_parameters: `requires unrestricted_pointer_parameters;`,
+ pointer_composite_access: `requires pointer_composite_access;`,
+};
+
+g.test('language_names')
+ .desc('Tests language extension names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', keysOf(kLanguageCases))
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ t.skipIf(!t.hasLanguageFeature(t.params.case), 'Missing language feature');
+ const code = `
+ ${kLanguageCases[t.params.case]}
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });
+
+const kSwizzleCases = [
+ 'x',
+ 'y',
+ 'z',
+ 'w',
+ 'xy',
+ 'yxz',
+ 'wxyz',
+ 'xyxy',
+ 'r',
+ 'g',
+ 'b',
+ 'a',
+ 'rgb',
+ 'arr',
+ 'bgra',
+ 'agra',
+];
+
+g.test('swizzle_names')
+ .desc('Tests swizzle names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', kSwizzleCases)
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ let code = `${t.params.decl} ${t.params.case} : u32 = 0;\n`;
+ if (t.params.case.length === 1) {
+ for (let i = 2; i <= 4; i++) {
+ code += `${t.params.decl} ${t.params.case.padEnd(i, t.params.case[0])} : u32 = 0;\n`;
+ }
+ }
+ code += `fn foo() {
+ var x : vec4f;
+ _ = x.${t.params.case};
+ `;
+ if (t.params.case.length === 1) {
+ for (let i = 2; i <= 4; i++) {
+ code += `_ = x.${t.params.case.padEnd(i, t.params.case[0])};\n`;
+ }
+ }
+ code += `}
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }`;
+ t.expectCompileResult(true, code);
+ });
+
+const kInterpolationTypeCases = ['perspective', 'linear', 'flat'];
+
+g.test('interpolation_type_names')
+ .desc('Tests interpolation type names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', kInterpolationTypeCases)
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ const code = `
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ @fragment fn main(@location(0) @interpolate(${t.params.case}) x : f32) { }
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });
+
+const kInterpolationSamplingCases = ['center', 'centroid', 'sample'];
+
+g.test('interpolation_sampling_names')
+ .desc('Tests interpolation type names do not use name resolution')
+ .params(u =>
+ u
+ .combine('case', kInterpolationSamplingCases)
+ .beginSubcases()
+ .combine('decl', ['override', 'const', 'var<private>'] as const)
+ )
+ .fn(t => {
+ const code = `
+ ${t.params.decl} ${t.params.case} : u32 = 0;
+ @fragment fn main(@location(0) @interpolate(perspective, ${t.params.case}) x : f32) { }
+ fn use_var() -> u32 {
+ return ${t.params.case};
+ }
+ `;
+
+ t.expectCompileResult(true, code);
+ });