Skip to content

Commit 663ea46

Browse files
authored
Add type tests for WGSL immediate pointers (#4675)
This patch extends type validation for the `immediate` address space. The pointer tests cover `ptr<immediate>` parsing, missing store types, invalid access modes, read-only pointer use, and immediate store types that must be rejected, including arrays and atomics. The type suites also recognize `immediate` as an address-space enumerant and check that `ref<immediate, T>` is not a nameable type.
1 parent e8389d8 commit 663ea46

3 files changed

Lines changed: 57 additions & 5 deletions

File tree

‎src/webgpu/shader/validation/types/enumerant.spec.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const kEnumerantValues = [
5151
'storage',
5252
'uniform',
5353
'handle',
54+
'immediate',
5455

5556
// Texel formats
5657
'rgba8unorm',

‎src/webgpu/shader/validation/types/pointer.spec.ts‎

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
getVarDeclShader,
1111
supportsWrite,
1212
ShaderStage,
13+
skipIfAddressSpaceNotSupported,
14+
skipIfImmediateDataNotSupported,
1315
} from '../decl/util.js';
1416
import { ShaderValidationTest } from '../shader_validation_test.js';
1517

@@ -19,11 +21,22 @@ g.test('missing_type')
1921
.desc('Test that pointer types require an element type')
2022
.params(u =>
2123
u
22-
.combine('aspace', ['function', 'private', 'workgroup', 'storage', 'uniform'] as const)
24+
.combine('aspace', [
25+
'function',
26+
'private',
27+
'workgroup',
28+
'storage',
29+
'uniform',
30+
'immediate',
31+
] as const)
2332
.combine('comma', ['', ','] as const)
2433
)
2534
.fn(t => {
26-
const code = `alias T = ptr<${t.params.aspace}${t.params.comma}>;`;
35+
if (t.params.aspace === 'immediate') {
36+
skipIfImmediateDataNotSupported(t);
37+
}
38+
const header = t.params.aspace === 'immediate' ? 'requires immediate_address_space;\n' : '';
39+
const code = `${header}alias T = ptr<${t.params.aspace}${t.params.comma}>;`;
2740
t.expectCompileResult(false, code);
2841
});
2942

@@ -37,13 +50,18 @@ g.test('address_space')
3750
'workgroup',
3851
'storage',
3952
'uniform',
53+
'immediate',
4054
'handle',
4155
'bad_aspace',
4256
] as const)
4357
.combine('comma', ['', ','] as const)
4458
)
4559
.fn(t => {
46-
const code = `alias T = ptr<${t.params.aspace}, u32${t.params.comma}>;`;
60+
if (t.params.aspace === 'immediate') {
61+
skipIfImmediateDataNotSupported(t);
62+
}
63+
const header = t.params.aspace === 'immediate' ? 'requires immediate_address_space;\n' : '';
64+
const code = `${header}alias T = ptr<${t.params.aspace}, u32${t.params.comma}>;`;
4765
const success = t.params.aspace !== 'handle' && t.params.aspace !== 'bad_aspace';
4866
t.expectCompileResult(success, code);
4967
});
@@ -52,13 +70,24 @@ g.test('access_mode')
5270
.desc('Test access mode in pointer type parameterization')
5371
.params(u =>
5472
u
55-
.combine('aspace', ['function', 'private', 'storage', 'uniform', 'workgroup'] as const)
73+
.combine('aspace', [
74+
'function',
75+
'private',
76+
'storage',
77+
'uniform',
78+
'workgroup',
79+
'immediate',
80+
] as const)
5681
.combine('access', ['read', 'write', 'read_write'] as const)
5782
.combine('comma', ['', ','] as const)
5883
)
5984
.fn(t => {
6085
// Default access mode is tested above.
61-
const code = `alias T = ptr<${t.params.aspace}, u32, ${t.params.access}${t.params.comma}>;`;
86+
if (t.params.aspace === 'immediate') {
87+
skipIfImmediateDataNotSupported(t);
88+
}
89+
const header = t.params.aspace === 'immediate' ? 'requires immediate_address_space;\n' : '';
90+
const code = `${header}alias T = ptr<${t.params.aspace}, u32, ${t.params.access}${t.params.comma}>;`;
6291
const success = t.params.aspace === 'storage' && t.params.access !== 'write';
6392
t.expectCompileResult(success, code);
6493
});
@@ -158,6 +187,7 @@ g.test('let_ptr_explicit_type_matches_var')
158187
.combine('ptrStoreType', ['i32', 'u32'])
159188
)
160189
.fn(t => {
190+
skipIfAddressSpaceNotSupported(t, t.params.addressSpace);
161191
// Match the address space and access mode.
162192
const prog = getVarDeclShader(t.params, `let p: ${pointerType(t.params)} = &x;`);
163193
const ok = t.params.ptrStoreType === 'i32'; // The store type matches the variable's store type.
@@ -178,6 +208,7 @@ g.test('let_ptr_reads')
178208
.combine('ptrStoreType', ['i32'])
179209
)
180210
.fn(t => {
211+
skipIfAddressSpaceNotSupported(t, t.params.addressSpace);
181212
// Try reading through the pointer.
182213
const typePart = t.params.inferPtrType ? `: ${pointerType(t.params)}` : '';
183214
const prog = getVarDeclShader(t.params, `let p${typePart} = &x; let read = *p;`);
@@ -200,6 +231,7 @@ g.test('let_ptr_writes')
200231
.combine('ptrStoreType', ['i32'])
201232
)
202233
.fn(t => {
234+
skipIfAddressSpaceNotSupported(t, t.params.addressSpace);
203235
// Try writing through the pointer.
204236
const typePart = t.params.inferPtrType ? `: ${pointerType(t.params)}` : '';
205237
const prog = getVarDeclShader(t.params, `let p${typePart} = &x; *p = 42;`);
@@ -243,6 +275,12 @@ const kStoreTypeNotInstantiable: Record<string, string> = {
243275
functionRTArray: 'alias p = ptr<function,array<i32>>;',
244276
RTArrayNotLast: 'struct S { a: array<i32>, b: i32 } alias p = ptr<storage,S>;',
245277
nestedRTArray: 'struct S { a: array<i32>, b: i32 } struct { s: S } alias p = ptr<storage,T>;',
278+
immediateBool: 'requires immediate_address_space; alias p = ptr<immediate,bool>;',
279+
immediateArray: 'requires immediate_address_space; alias p = ptr<immediate,array<u32, 4>>;',
280+
immediateStructWithArray:
281+
'requires immediate_address_space; struct S { data: array<u32, 4> } alias p = ptr<immediate,S>;',
282+
immediateAtomic: 'requires immediate_address_space; alias p = ptr<immediate,atomic<u32>>;',
283+
immediateRuntimeArray: 'requires immediate_address_space; alias p = ptr<immediate,array<u32>>;',
246284
} as const;
247285

248286
g.test('ptr_not_instantiable')

‎src/webgpu/shader/validation/types/ref.spec.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Validation tests for ref types
33
`;
44

55
import { makeTestGroup } from '../../../../common/framework/test_group.js';
6+
import { skipIfImmediateDataNotSupported } from '../decl/util.js';
67
import { ShaderValidationTest } from '../shader_validation_test.js';
78

89
export const g = makeTestGroup(ShaderValidationTest);
@@ -55,3 +56,15 @@ g.test('not_typeable_alias')
5556
alias a = ${t.params.view}<private, ${t.params.type}>;`;
5657
t.expectCompileResult(t.params.view === 'ptr', code);
5758
});
59+
60+
g.test('not_typeable_ref_immediate')
61+
.desc('Test that ref<immediate, T> cannot be written as an explicit type.')
62+
.params(u => u.combine('type', kTypes))
63+
.fn(t => {
64+
skipIfImmediateDataNotSupported(t);
65+
const code = `
66+
requires immediate_address_space;
67+
struct S { a : u32 }
68+
alias a = ref<immediate, ${t.params.type}>;`;
69+
t.expectCompileResult(false, code);
70+
});

0 commit comments

Comments
 (0)