diff --git a/src/webgpu/shader/validation/types/enumerant.spec.ts b/src/webgpu/shader/validation/types/enumerant.spec.ts index 4cebb35b9c5a..342b105290a2 100644 --- a/src/webgpu/shader/validation/types/enumerant.spec.ts +++ b/src/webgpu/shader/validation/types/enumerant.spec.ts @@ -51,6 +51,7 @@ const kEnumerantValues = [ 'storage', 'uniform', 'handle', + 'immediate', // Texel formats 'rgba8unorm', diff --git a/src/webgpu/shader/validation/types/pointer.spec.ts b/src/webgpu/shader/validation/types/pointer.spec.ts index c787668ad5e4..8bc1389ae3cd 100644 --- a/src/webgpu/shader/validation/types/pointer.spec.ts +++ b/src/webgpu/shader/validation/types/pointer.spec.ts @@ -10,6 +10,8 @@ import { getVarDeclShader, supportsWrite, ShaderStage, + skipIfAddressSpaceNotSupported, + skipIfImmediateDataNotSupported, } from '../decl/util.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; @@ -19,11 +21,22 @@ g.test('missing_type') .desc('Test that pointer types require an element type') .params(u => u - .combine('aspace', ['function', 'private', 'workgroup', 'storage', 'uniform'] as const) + .combine('aspace', [ + 'function', + 'private', + 'workgroup', + 'storage', + 'uniform', + 'immediate', + ] as const) .combine('comma', ['', ','] as const) ) .fn(t => { - const code = `alias T = ptr<${t.params.aspace}${t.params.comma}>;`; + if (t.params.aspace === 'immediate') { + skipIfImmediateDataNotSupported(t); + } + const header = t.params.aspace === 'immediate' ? 'requires immediate_address_space;\n' : ''; + const code = `${header}alias T = ptr<${t.params.aspace}${t.params.comma}>;`; t.expectCompileResult(false, code); }); @@ -37,13 +50,18 @@ g.test('address_space') 'workgroup', 'storage', 'uniform', + 'immediate', 'handle', 'bad_aspace', ] as const) .combine('comma', ['', ','] as const) ) .fn(t => { - const code = `alias T = ptr<${t.params.aspace}, u32${t.params.comma}>;`; + if (t.params.aspace === 'immediate') { + skipIfImmediateDataNotSupported(t); + } + const header = t.params.aspace === 'immediate' ? 'requires immediate_address_space;\n' : ''; + const code = `${header}alias T = ptr<${t.params.aspace}, u32${t.params.comma}>;`; const success = t.params.aspace !== 'handle' && t.params.aspace !== 'bad_aspace'; t.expectCompileResult(success, code); }); @@ -52,13 +70,24 @@ g.test('access_mode') .desc('Test access mode in pointer type parameterization') .params(u => u - .combine('aspace', ['function', 'private', 'storage', 'uniform', 'workgroup'] as const) + .combine('aspace', [ + 'function', + 'private', + 'storage', + 'uniform', + 'workgroup', + 'immediate', + ] as const) .combine('access', ['read', 'write', 'read_write'] as const) .combine('comma', ['', ','] as const) ) .fn(t => { // Default access mode is tested above. - const code = `alias T = ptr<${t.params.aspace}, u32, ${t.params.access}${t.params.comma}>;`; + if (t.params.aspace === 'immediate') { + skipIfImmediateDataNotSupported(t); + } + const header = t.params.aspace === 'immediate' ? 'requires immediate_address_space;\n' : ''; + const code = `${header}alias T = ptr<${t.params.aspace}, u32, ${t.params.access}${t.params.comma}>;`; const success = t.params.aspace === 'storage' && t.params.access !== 'write'; t.expectCompileResult(success, code); }); @@ -158,6 +187,7 @@ g.test('let_ptr_explicit_type_matches_var') .combine('ptrStoreType', ['i32', 'u32']) ) .fn(t => { + skipIfAddressSpaceNotSupported(t, t.params.addressSpace); // Match the address space and access mode. const prog = getVarDeclShader(t.params, `let p: ${pointerType(t.params)} = &x;`); const ok = t.params.ptrStoreType === 'i32'; // The store type matches the variable's store type. @@ -178,6 +208,7 @@ g.test('let_ptr_reads') .combine('ptrStoreType', ['i32']) ) .fn(t => { + skipIfAddressSpaceNotSupported(t, t.params.addressSpace); // Try reading through the pointer. const typePart = t.params.inferPtrType ? `: ${pointerType(t.params)}` : ''; const prog = getVarDeclShader(t.params, `let p${typePart} = &x; let read = *p;`); @@ -200,6 +231,7 @@ g.test('let_ptr_writes') .combine('ptrStoreType', ['i32']) ) .fn(t => { + skipIfAddressSpaceNotSupported(t, t.params.addressSpace); // Try writing through the pointer. const typePart = t.params.inferPtrType ? `: ${pointerType(t.params)}` : ''; const prog = getVarDeclShader(t.params, `let p${typePart} = &x; *p = 42;`); @@ -243,6 +275,12 @@ const kStoreTypeNotInstantiable: Record = { functionRTArray: 'alias p = ptr>;', RTArrayNotLast: 'struct S { a: array, b: i32 } alias p = ptr;', nestedRTArray: 'struct S { a: array, b: i32 } struct { s: S } alias p = ptr;', + immediateBool: 'requires immediate_address_space; alias p = ptr;', + immediateArray: 'requires immediate_address_space; alias p = ptr>;', + immediateStructWithArray: + 'requires immediate_address_space; struct S { data: array } alias p = ptr;', + immediateAtomic: 'requires immediate_address_space; alias p = ptr>;', + immediateRuntimeArray: 'requires immediate_address_space; alias p = ptr>;', } as const; g.test('ptr_not_instantiable') diff --git a/src/webgpu/shader/validation/types/ref.spec.ts b/src/webgpu/shader/validation/types/ref.spec.ts index 96f4e464e296..3e0f2f56187d 100644 --- a/src/webgpu/shader/validation/types/ref.spec.ts +++ b/src/webgpu/shader/validation/types/ref.spec.ts @@ -3,6 +3,7 @@ Validation tests for ref types `; import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { skipIfImmediateDataNotSupported } from '../decl/util.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); @@ -55,3 +56,15 @@ g.test('not_typeable_alias') alias a = ${t.params.view};`; t.expectCompileResult(t.params.view === 'ptr', code); }); + +g.test('not_typeable_ref_immediate') + .desc('Test that ref cannot be written as an explicit type.') + .params(u => u.combine('type', kTypes)) + .fn(t => { + skipIfImmediateDataNotSupported(t); + const code = ` + requires immediate_address_space; + struct S { a : u32 } + alias a = ref;`; + t.expectCompileResult(false, code); + });