summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/functions/restrictions.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/functions/restrictions.spec.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/functions/restrictions.spec.ts313
1 files changed, 185 insertions, 128 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/functions/restrictions.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/functions/restrictions.spec.ts
index b6affd14d6..7c79e6c5ea 100644
--- a/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/functions/restrictions.spec.ts
+++ b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/validation/functions/restrictions.spec.ts
@@ -12,6 +12,30 @@ interface VertexPosCase {
valid: boolean;
}
+const kCCommonTypeDecls = `
+struct runtime_array_struct {
+ arr : array<u32>
+}
+
+struct constructible {
+ a : i32,
+ b : u32,
+ c : f32,
+ d : bool,
+}
+
+struct host_shareable {
+ a : i32,
+ b : u32,
+ c : f32,
+}
+
+struct struct_with_array {
+ a : array<constructible, 4>
+}
+
+`;
+
const kVertexPosCases: Record<string, VertexPosCase> = {
bare_position: { name: `@builtin(position) vec4f`, value: `vec4f()`, valid: true },
nested_position: { name: `pos_struct`, value: `pos_struct()`, valid: true },
@@ -145,20 +169,7 @@ g.test('function_return_types')
const code = `
${enable}
-struct runtime_array_struct {
- arr : array<u32>
-}
-
-struct constructible {
- a : i32,
- b : u32,
- c : f32,
- d : bool,
-}
-
-struct struct_with_array {
- a : array<constructible, 4>
-}
+${kCCommonTypeDecls}
struct atomic_struct {
a : atomic<u32>
@@ -192,7 +203,7 @@ fn foo() -> ${testcase.name} {
interface ParamTypeCase {
name: string;
- valid: boolean;
+ valid: boolean | 'with_unrestricted_pointer_parameters';
}
const kFunctionParamTypeCases: Record<string, ParamTypeCase> = {
@@ -246,21 +257,42 @@ const kFunctionParamTypeCases: Record<string, ParamTypeCase> = {
ptr3: { name: `ptr<private, u32>`, valid: true },
ptr4: { name: `ptr<private, constructible>`, valid: true },
+ // Pointers only valid with unrestricted_pointer_parameters
+ ptr5: { name: `ptr<storage, u32>`, valid: 'with_unrestricted_pointer_parameters' },
+ ptr6: { name: `ptr<storage, u32, read>`, valid: 'with_unrestricted_pointer_parameters' },
+ ptr7: { name: `ptr<storage, u32, read_write>`, valid: 'with_unrestricted_pointer_parameters' },
+ ptr8: { name: `ptr<uniform, u32>`, valid: 'with_unrestricted_pointer_parameters' },
+ ptr9: { name: `ptr<workgroup, u32>`, valid: 'with_unrestricted_pointer_parameters' },
+ ptr10: {
+ name: `ptr<storage, host_shareable, read_write>`,
+ valid: 'with_unrestricted_pointer_parameters',
+ },
+ ptr11: {
+ name: `ptr<storage, host_shareable, read>`,
+ valid: 'with_unrestricted_pointer_parameters',
+ },
+ ptr12: {
+ name: `ptr<uniform, host_shareable>`,
+ valid: 'with_unrestricted_pointer_parameters',
+ },
+ ptrWorkgroupAtomic: {
+ name: `ptr<workgroup, atomic<u32>>`,
+ valid: 'with_unrestricted_pointer_parameters',
+ },
+ ptrWorkgroupNestedAtomic: {
+ name: `ptr<workgroup, array<atomic<u32>,1>>`,
+ valid: 'with_unrestricted_pointer_parameters',
+ },
+
// Invalid pointers.
- ptr5: { name: `ptr<storage, u32>`, valid: false },
- ptr6: { name: `ptr<storage, u32, read>`, valid: false },
- ptr7: { name: `ptr<storage, u32, read_write>`, valid: false },
- ptr8: { name: `ptr<uniform, u32>`, valid: false },
- ptr9: { name: `ptr<workgroup, u32>`, valid: false },
- ptr10: { name: `ptr<handle, u32>`, valid: false }, // Can't spell handle address space
- ptr12: { name: `ptr<not_an_address_space, u32>`, valid: false },
- ptr13: { name: `ptr<storage>`, valid: false }, // No store type
- ptr14: { name: `ptr<private,clamp>`, valid: false }, // Invalid store type
- ptr15: { name: `ptr<private,u32,read>`, valid: false }, // Can't specify access mode
- ptr16: { name: `ptr<private,u32,write>`, valid: false }, // Can't specify access mode
- ptr17: { name: `ptr<private,u32,read_write>`, valid: false }, // Can't specify access mode
- ptrWorkgroupAtomic: { name: `ptr<workgroup, atomic<u32>>`, valid: false },
- ptrWorkgroupNestedAtomic: { name: `ptr<workgroup, array<atomic<u32>,1>>`, valid: false },
+ invalid_ptr1: { name: `ptr<handle, u32>`, valid: false }, // Can't spell handle address space
+ invalid_ptr2: { name: `ptr<not_an_address_space, u32>`, valid: false },
+ invalid_ptr3: { name: `ptr<storage>`, valid: false }, // No store type
+ invalid_ptr4: { name: `ptr<private,u32,read>`, valid: false }, // Can't specify access mode
+ invalid_ptr5: { name: `ptr<private,u32,write>`, valid: false }, // Can't specify access mode
+ invalid_ptr6: { name: `ptr<private,u32,read_write>`, valid: false }, // Can't specify access mode
+ invalid_ptr7: { name: `ptr<private,clamp>`, valid: false }, // Invalid store type
+ invalid_ptr8: { name: `ptr<function, texture_external>`, valid: false }, // non-constructable pointer type
};
g.test('function_parameter_types')
@@ -278,30 +310,23 @@ g.test('function_parameter_types')
const code = `
${enable}
-struct runtime_array_struct {
- arr : array<u32>
-}
-
-struct constructible {
- a : i32,
- b : u32,
- c : f32,
- d : bool,
-}
-
-struct struct_with_array {
- a : array<constructible, 4>
-}
+${kCCommonTypeDecls}
fn foo(param : ${testcase.name}) {
}`;
- t.expectCompileResult(testcase.valid, code);
+ let isValid = testcase.valid;
+ if (isValid === 'with_unrestricted_pointer_parameters') {
+ isValid = t.hasLanguageFeature('unrestricted_pointer_parameters');
+ }
+
+ t.expectCompileResult(isValid, code);
});
interface ParamValueCase {
value: string;
matches: string[];
+ needsUnrestrictedPointerParameters?: boolean;
}
const kFunctionParamValueCases: Record<string, ParamValueCase> = {
@@ -426,15 +451,47 @@ const kFunctionParamValueCases: Record<string, ParamValueCase> = {
ptr3: { value: `&g_u32`, matches: ['ptr3'] },
ptr4: { value: `&g_constructible`, matches: ['ptr4'] },
- // Invalid pointers
- ptr5: { value: `&f_constructible.b`, matches: [] },
- ptr6: { value: `&g_constructible.b`, matches: [] },
- ptr7: { value: `&f_struct_with_array.a[1].b`, matches: [] },
- ptr8: { value: `&g_struct_with_array.a[2]`, matches: [] },
- ptr9: { value: `&ro_constructible.b`, matches: [] },
- ptr10: { value: `&rw_constructible`, matches: [] },
- ptr11: { value: `&uniform_constructible`, matches: [] },
- ptr12: { value: `&ro_constructible`, matches: [] },
+ // Requires 'unrestricted_pointer_parameters' WGSL feature
+ ptr5: {
+ value: `&f_constructible.b`,
+ matches: ['ptr1'],
+ needsUnrestrictedPointerParameters: true,
+ },
+ ptr6: {
+ value: `&g_constructible.b`,
+ matches: ['ptr3'],
+ needsUnrestrictedPointerParameters: true,
+ },
+ ptr7: {
+ value: `&f_struct_with_array.a[1].b`,
+ matches: ['ptr1'],
+ needsUnrestrictedPointerParameters: true,
+ },
+ ptr8: {
+ value: `&g_struct_with_array.a[2]`,
+ matches: ['ptr4'],
+ needsUnrestrictedPointerParameters: true,
+ },
+ ptr9: {
+ value: `&ro_host_shareable.b`,
+ matches: ['ptr5', 'ptr6'],
+ needsUnrestrictedPointerParameters: true,
+ },
+ ptr10: {
+ value: `&rw_host_shareable`,
+ matches: ['ptr10'],
+ needsUnrestrictedPointerParameters: true,
+ },
+ ptr11: {
+ value: `&ro_host_shareable`,
+ matches: ['ptr11'],
+ needsUnrestrictedPointerParameters: true,
+ },
+ ptr12: {
+ value: `&uniform_host_shareable`,
+ matches: ['ptr12'],
+ needsUnrestrictedPointerParameters: true,
+ },
};
function parameterMatches(decl: string, matches: string[]): boolean {
@@ -454,10 +511,11 @@ g.test('function_parameter_matching')
.params(u =>
u
.combine('decl', keysOf(kFunctionParamTypeCases))
- .combine('arg', keysOf(kFunctionParamValueCases))
.filter(u => {
- return kFunctionParamTypeCases[u.decl].valid;
+ return kFunctionParamTypeCases[u.decl].valid !== false;
})
+ .beginSubcases()
+ .combine('arg', keysOf(kFunctionParamValueCases))
)
.beforeAllSubcases(t => {
if (kFunctionParamTypeCases[t.params.decl].name === 'f16') {
@@ -471,26 +529,7 @@ g.test('function_parameter_matching')
const code = `
${enable}
-struct runtime_array_struct {
- arr : array<u32>
-}
-
-struct constructible {
- a : i32,
- b : u32,
- c : f32,
- d : bool,
-}
-
-struct host_shareable {
- a : i32,
- b : u32,
- c : f32,
-}
-
-struct struct_with_array {
- a : array<constructible, 4>
-}
+${kCCommonTypeDecls}
@group(0) @binding(0)
var t : texture_2d<f32>;
@group(0) @binding(1)
@@ -507,11 +546,11 @@ var t_multisampled : texture_multisampled_2d<f32>;
var t_external : texture_external;
@group(1) @binding(0)
-var<storage> ro_constructible : host_shareable;
+var<storage> ro_host_shareable : host_shareable;
@group(1) @binding(1)
-var<storage, read_write> rw_constructible : host_shareable;
+var<storage, read_write> rw_host_shareable : host_shareable;
@group(1) @binding(2)
-var<uniform> uniform_constructible : host_shareable;
+var<uniform> uniform_host_shareable : host_shareable;
fn bar(param : ${param.name}) { }
@@ -568,7 +607,17 @@ fn foo() {
}
`;
- t.expectCompileResult(parameterMatches(t.params.decl, arg.matches), code);
+ const needsUnrestrictedPointerParameters =
+ (kFunctionParamTypeCases[t.params.decl].valid === 'with_unrestricted_pointer_parameters' ||
+ arg.needsUnrestrictedPointerParameters) ??
+ false;
+
+ let isValid = parameterMatches(t.params.decl, arg.matches);
+ if (isValid && needsUnrestrictedPointerParameters) {
+ isValid = t.hasLanguageFeature('unrestricted_pointer_parameters');
+ }
+
+ t.expectCompileResult(isValid, code);
});
g.test('no_direct_recursion')
@@ -691,67 +740,75 @@ function checkArgTypeMatch(param_type: string, arg_matches: string[]): boolean {
return false;
}
-g.test('call_arg_types_match_params')
+g.test('call_arg_types_match_1_param')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#function-calls')
+ .desc(`Test that the argument types match in order`)
+ .params(u =>
+ u
+ .combine('p1_type', kParamsTypes) //
+ .beginSubcases()
+ .combine('arg1_value', keysOf(kArgValues))
+ )
+ .fn(t => {
+ const code = `
+fn bar(p1 : ${t.params.p1_type}) { }
+fn foo() {
+ bar(${kArgValues[t.params.arg1_value].value});
+}`;
+
+ const res = checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches);
+ t.expectCompileResult(res, code);
+ });
+
+g.test('call_arg_types_match_2_params')
+ .specURL('https://gpuweb.github.io/gpuweb/wgsl/#function-calls')
+ .desc(`Test that the argument types match in order`)
+ .params(u =>
+ u
+ .combine('p1_type', kParamsTypes)
+ .combine('p2_type', kParamsTypes)
+ .beginSubcases()
+ .combine('arg1_value', keysOf(kArgValues))
+ .combine('arg2_value', keysOf(kArgValues))
+ )
+ .fn(t => {
+ const code = `
+fn bar(p1 : ${t.params.p1_type}, p2 : ${t.params.p2_type}) { }
+fn foo() {
+ bar(${kArgValues[t.params.arg1_value].value}, ${kArgValues[t.params.arg2_value].value});
+}`;
+
+ const res =
+ checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches) &&
+ checkArgTypeMatch(t.params.p2_type, kArgValues[t.params.arg2_value].matches);
+ t.expectCompileResult(res, code);
+ });
+
+g.test('call_arg_types_match_3_params')
.specURL('https://gpuweb.github.io/gpuweb/wgsl/#function-calls')
.desc(`Test that the argument types match in order`)
.params(u =>
u
- .combine('num_args', [1, 2, 3] as const)
.combine('p1_type', kParamsTypes)
.combine('p2_type', kParamsTypes)
.combine('p3_type', kParamsTypes)
+ .beginSubcases()
.combine('arg1_value', keysOf(kArgValues))
.combine('arg2_value', keysOf(kArgValues))
.combine('arg3_value', keysOf(kArgValues))
)
.fn(t => {
- let code = `
- fn bar(`;
- for (let i = 0; i < t.params.num_args; i++) {
- switch (i) {
- case 0:
- default: {
- code += `p${i} : ${t.params.p1_type},`;
- break;
- }
- case 1: {
- code += `p${i} : ${t.params.p2_type},`;
- break;
- }
- case 2: {
- code += `p${i} : ${t.params.p3_type},`;
- break;
- }
- }
- }
- code += `) { }
- fn foo() {
- bar(`;
- for (let i = 0; i < t.params.num_args; i++) {
- switch (i) {
- case 0:
- default: {
- code += `${kArgValues[t.params.arg1_value].value},`;
- break;
- }
- case 1: {
- code += `${kArgValues[t.params.arg2_value].value},`;
- break;
- }
- case 2: {
- code += `${kArgValues[t.params.arg3_value].value},`;
- break;
- }
- }
- }
- code += `);\n}`;
+ const code = `
+fn bar(p1 : ${t.params.p1_type}, p2 : ${t.params.p2_type}, p3 : ${t.params.p3_type}) { }
+fn foo() {
+ bar(${kArgValues[t.params.arg1_value].value},
+ ${kArgValues[t.params.arg2_value].value},
+ ${kArgValues[t.params.arg3_value].value});
+}`;
- let res = checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches);
- if (res && t.params.num_args > 1) {
- res = checkArgTypeMatch(t.params.p2_type, kArgValues[t.params.arg2_value].matches);
- }
- if (res && t.params.num_args > 2) {
- res = checkArgTypeMatch(t.params.p3_type, kArgValues[t.params.arg3_value].matches);
- }
+ const res =
+ checkArgTypeMatch(t.params.p1_type, kArgValues[t.params.arg1_value].matches) &&
+ checkArgTypeMatch(t.params.p2_type, kArgValues[t.params.arg2_value].matches) &&
+ checkArgTypeMatch(t.params.p3_type, kArgValues[t.params.arg3_value].matches);
t.expectCompileResult(res, code);
});