From 807721dde1a6ccbfd9943b3bb030ca363dd695e0 Mon Sep 17 00:00:00 2001 From: James Price Date: Fri, 26 Jan 2024 14:44:23 -0500 Subject: [PATCH] shader/validation: Test store types for var decls Make sure the implementation accepts a store type iff that type is allowed for the given address space. Issue #1570 --- src/webgpu/listing_meta.json | 2 + src/webgpu/shader/validation/decl/var.spec.ts | 330 ++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 src/webgpu/shader/validation/decl/var.spec.ts diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index 3eff54ce5057..f80006ea0593 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -1726,6 +1726,8 @@ "webgpu:shader,validation,decl,ptr_spelling:ptr_bad_store_type:*": { "subcaseMS": 0.967 }, "webgpu:shader,validation,decl,ptr_spelling:ptr_handle_space_invalid:*": { "subcaseMS": 1.000 }, "webgpu:shader,validation,decl,ptr_spelling:ptr_not_instantiable:*": { "subcaseMS": 1.310 }, + "webgpu:shader,validation,decl,var:module_scope_types:*": { "subcaseMS": 1.000 }, + "webgpu:shader,validation,decl,var:function_scope_types:*": { "subcaseMS": 1.000 }, "webgpu:shader,validation,decl,var_access_mode:explicit_access_mode:*": { "subcaseMS": 1.373 }, "webgpu:shader,validation,decl,var_access_mode:implicit_access_mode:*": { "subcaseMS": 1.000 }, "webgpu:shader,validation,decl,var_access_mode:read_access:*": { "subcaseMS": 1.177 }, diff --git a/src/webgpu/shader/validation/decl/var.spec.ts b/src/webgpu/shader/validation/decl/var.spec.ts new file mode 100644 index 000000000000..bf2772efa1c8 --- /dev/null +++ b/src/webgpu/shader/validation/decl/var.spec.ts @@ -0,0 +1,330 @@ +export const description = ` +Validation tests for host-shareable types. +`; + +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); + +// The set of types and their properties. +const kTypes = { + // Scalars. + bool: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + i32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + u32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + f32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + f16: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: true, + }, + + // Vectors. + 'vec2': { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + vec3i: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + vec4u: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + vec2f: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + vec3h: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: true, + }, + + // Matrices. + mat2x2f: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + mat3x4h: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: true, + }, + + // Atomics. + 'atomic': { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: true, + requiresF16: false, + }, + 'atomic': { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: true, + requiresF16: false, + }, + + // Arrays. + 'array>': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false, + }, + 'array, 4>': { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + 'array': { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false, + }, + 'array': { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + 'array': { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + 'array': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: true, + requiresF16: false, + }, + + // Structures. + S_u32: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + S_bool: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + S_S_bool: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + S_array_vec4u: { + isHostShareable: true, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false, + }, + S_array_vec4u_4: { + isHostShareable: true, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + S_array_bool_4: { + isHostShareable: false, + isConstructible: true, + isFixedFootprint: true, + requiresF16: false, + }, + + // Misc. + 'ptr': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false, + }, + sampler: { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false, + }, + 'texture_2d': { + isHostShareable: false, + isConstructible: false, + isFixedFootprint: false, + requiresF16: false, + }, +}; + +g.test('module_scope_types') + .desc('Test that only types that are allowed for a given address space are accepted.') + .params(u => + u + .combine('type', keysOf(kTypes)) + .combine('kind', [ + 'comment', + 'handle', + 'private', + 'storage_ro', + 'storage_rw', + 'uniform', + 'workgroup', + ]) + .combine('via_alias', [false, true]) + ) + .beforeAllSubcases(t => { + if (kTypes[t.params.type].requiresF16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } + }) + .fn(t => { + const type = kTypes[t.params.type]; + const isAtomic = t.params.type.indexOf('atomic') > -1; + + let decl = '<>'; + let shouldPass = false; + switch (t.params.kind) { + case 'comment': + // Control case to make sure all types are spelled correctly. + // We always emit an alias to the target type. + decl = '// '; + shouldPass = true; + break; + case 'handle': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = t.params.type.indexOf('texture') > -1 || t.params.type.indexOf('sampler') > -1; + break; + case 'private': + decl = 'var foo : '; + shouldPass = type.isConstructible; + break; + case 'storage_ro': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = type.isHostShareable && !isAtomic; + break; + case 'storage_rw': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = type.isHostShareable; + break; + case 'uniform': + decl = '@group(0) @binding(0) var foo : '; + shouldPass = type.isHostShareable && type.isConstructible; + break; + case 'workgroup': + decl = 'var foo : '; + shouldPass = type.isFixedFootprint; + break; + } + + const wgsl = `${type.requiresF16 ? 'enable f16;' : ''} + const array_size_const = 4; + override array_size_override = 4; + + struct S_u32 { a : u32 } + struct S_bool { a : bool } + struct S_S_bool { a : S_bool } + struct S_array_vec4u { a : array } + struct S_array_vec4u_4 { a : array } + struct S_array_bool_4 { a : array } + + alias MyType = ${t.params.type}; + + ${decl} ${t.params.via_alias ? 'MyType' : t.params.type}; + `; + + t.expectCompileResult(shouldPass, wgsl); + }); + +g.test('function_scope_types') + .desc('Test that only types that are allowed for a given address space are accepted.') + .params(u => + u + .combine('type', keysOf(kTypes)) + .combine('kind', ['comment', 'var']) + .combine('via_alias', [false, true]) + ) + .beforeAllSubcases(t => { + if (kTypes[t.params.type].requiresF16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } + }) + .fn(t => { + const type = kTypes[t.params.type]; + + let decl = '<>'; + let shouldPass = false; + switch (t.params.kind) { + case 'comment': + // Control case to make sure all types are spelled correctly. + // We always emit an alias to the target type. + decl = '// '; + shouldPass = true; + break; + case 'var': + decl = 'var foo : '; + shouldPass = type.isConstructible; + break; + } + + const wgsl = `${type.requiresF16 ? 'enable f16;' : ''} + const array_size_const = 4; + override array_size_override = 4; + + struct S_u32 { a : u32 } + struct S_bool { a : bool } + struct S_S_bool { a : S_bool } + struct S_array_vec4u { a : array } + struct S_array_vec4u_4 { a : array } + struct S_array_bool_4 { a : array } + + alias MyType = ${t.params.type}; + + fn foo() { + ${decl} ${t.params.via_alias ? 'MyType' : t.params.type}; + }`; + + t.expectCompileResult(shouldPass, wgsl); + });