diff --git a/src/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.ts b/src/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.ts index 97ab7e8e4750..32f826c48816 100644 --- a/src/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.ts +++ b/src/webgpu/shader/validation/expression/unary/address_of_and_indirection.spec.ts @@ -4,11 +4,12 @@ Validation tests for unary address-of and indirection (dereference) import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { keysOf } from '../../../../../common/util/data_tables.js'; +import { skipIfImmediateDataNotSupported } from '../../decl/util.js'; import { ShaderValidationTest } from '../../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); -const kAddressSpaces = ['function', 'private', 'workgroup', 'uniform', 'storage']; +const kAddressSpaces = ['function', 'private', 'workgroup', 'uniform', 'storage', 'immediate']; const kAccessModes = ['read', 'read_write']; const kStorageTypes = ['bool', 'u32', 'i32', 'f32', 'f16']; const kCompositeTypes = ['array', 'struct', 'vec', 'mat']; @@ -49,16 +50,25 @@ g.test('basic') } return true; }) + .filter(t => { + if (t.addressSpace !== 'immediate') return true; + return t.storageType !== 'bool'; + }) .filter(t => { // This test does not test composite access return !kDerefTypes[t.derefType].requires_pointer_composite_access; }) ) .fn(t => { + if (t.params.addressSpace === 'immediate') { + skipIfImmediateDataNotSupported(t); + } const isLocal = t.params.addressSpace === 'function'; const deref = kDerefTypes[t.params.derefType]; // Only specify access mode for storage buffers const commaAccessMode = t.params.addressSpace === 'storage' ? `, ${t.params.accessMode}` : ''; + const header = + t.params.addressSpace === 'immediate' ? 'requires immediate_address_space;\n' : ''; let varDecl = ''; if (t.params.addressSpace === 'uniform' || t.params.addressSpace === 'storage') { @@ -66,7 +76,7 @@ g.test('basic') } varDecl += `var<${t.params.addressSpace}${commaAccessMode}> a : VarType;`; - const wgsl = ` + const wgsl = `${header} ${t.params.storageType === 'f16' ? 'enable f16;' : ''} alias VarType = ${t.params.storageType}; @@ -111,12 +121,21 @@ g.test('composite') } return true; }) + .filter(t => { + if (t.addressSpace !== 'immediate') return true; + return t.compositeType !== 'array' && t.storageType !== 'bool'; + }) ) .fn(t => { + if (t.params.addressSpace === 'immediate') { + skipIfImmediateDataNotSupported(t); + } const isLocal = t.params.addressSpace === 'function'; const deref = kDerefTypes[t.params.derefType]; // Only specify access mode for storage buffers const commaAccessMode = t.params.addressSpace === 'storage' ? `, ${t.params.accessMode}` : ''; + const header = + t.params.addressSpace === 'immediate' ? 'requires immediate_address_space;\n' : ''; let varDecl = ''; if (t.params.addressSpace === 'uniform' || t.params.addressSpace === 'storage') { @@ -124,7 +143,7 @@ g.test('composite') } varDecl += `var<${t.params.addressSpace}${commaAccessMode}> a : VarType;`; - let wgsl = ` + let wgsl = `${header} ${t.params.storageType === 'f16' ? 'enable f16;' : ''}`; switch (t.params.compositeType) { diff --git a/src/webgpu/shader/validation/functions/restrictions.spec.ts b/src/webgpu/shader/validation/functions/restrictions.spec.ts index 73c3a376765e..84eef391760d 100644 --- a/src/webgpu/shader/validation/functions/restrictions.spec.ts +++ b/src/webgpu/shader/validation/functions/restrictions.spec.ts @@ -2,6 +2,7 @@ export const description = `Validation tests for function restrictions`; import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { keysOf } from '../../../../common/util/data_tables.js'; +import { skipIfImmediateDataNotSupported } from '../decl/util.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); @@ -274,6 +275,10 @@ const kFunctionParamTypeCases: Record = { name: `ptr`, valid: 'with_unrestricted_pointer_parameters', }, + ptrImmediate: { + name: `ptr`, + valid: 'with_unrestricted_pointer_parameters', + }, ptrWorkgroupAtomic: { name: `ptr>`, valid: 'with_unrestricted_pointer_parameters', @@ -304,6 +309,12 @@ const kFunctionParamTypeCases: Record = { invalid_ptr6: { name: `ptr`, valid: false }, // Can't specify access mode invalid_ptr7: { name: `ptr`, valid: false }, // Invalid store type invalid_ptr8: { name: `ptr`, valid: false }, // non-constructible pointer type + invalid_ptr_immediate_access_read: { name: `ptr`, valid: false }, + invalid_ptr_immediate_access_write: { name: `ptr`, valid: false }, + invalid_ptr_immediate_access_read_write: { + name: `ptr`, + valid: false, + }, }; g.test('function_parameter_types') @@ -313,8 +324,20 @@ g.test('function_parameter_types') .fn(t => { const testcase = kFunctionParamTypeCases[t.params.case]; const enable = testcase.name === 'f16' ? 'enable f16;' : ''; + const needsImmediate = testcase.name.includes('immediate'); + if (needsImmediate) { + skipIfImmediateDataNotSupported(t); + } + const immediateRequires = needsImmediate ? 'requires immediate_address_space;' : ''; + const unrestrictedRequires = + testcase.valid === 'with_unrestricted_pointer_parameters' && + t.hasLanguageFeature('unrestricted_pointer_parameters') + ? 'requires unrestricted_pointer_parameters;' + : ''; const code = ` ${enable} +${immediateRequires} +${unrestrictedRequires} ${kCCommonTypeDecls} @@ -504,6 +527,11 @@ const kFunctionParamValueCases: Record = { matches: ['ptr12'], needsUnrestrictedPointerParameters: true, }, + ptrImmediate: { + value: `&immediate_u32`, + matches: ['ptrImmediate'], + needsUnrestrictedPointerParameters: true, + }, ptrWorkgroupOverrideNoDefault: { value: `&wg_override_no_default`, matches: ['ptrWorkgroupOverrideNoDefault'], @@ -548,8 +576,23 @@ g.test('function_parameter_matching') const param = kFunctionParamTypeCases[t.params.decl]; const arg = kFunctionParamValueCases[t.params.arg]; const enable = param.name === 'f16' ? 'enable f16;' : ''; + const needsUnrestrictedPointerParameters = + (kFunctionParamTypeCases[t.params.decl].valid === 'with_unrestricted_pointer_parameters' || + arg.needsUnrestrictedPointerParameters) ?? + false; + const needsImmediate = param.name.includes('immediate') || t.params.arg === 'ptrImmediate'; + if (needsImmediate) { + skipIfImmediateDataNotSupported(t); + } + const immediateRequires = needsImmediate ? 'requires immediate_address_space;' : ''; + const unrestrictedRequires = + needsUnrestrictedPointerParameters && t.hasLanguageFeature('unrestricted_pointer_parameters') + ? 'requires unrestricted_pointer_parameters;' + : ''; const code = ` ${enable} +${immediateRequires} +${unrestrictedRequires} ${kCCommonTypeDecls} @group(0) @binding(0) @@ -573,6 +616,7 @@ var ro_host_shareable : host_shareable; var rw_host_shareable : host_shareable; @group(1) @binding(2) var uniform_host_shareable : host_shareable; +${needsImmediate ? 'var immediate_u32 : u32;' : ''} fn bar(param : ${param.name}) { } @@ -638,11 +682,6 @@ fn foo() { } `; - 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'); diff --git a/src/webgpu/shader/validation/uniformity/uniformity.spec.ts b/src/webgpu/shader/validation/uniformity/uniformity.spec.ts index cbc8476d466e..f3a3bddb5215 100644 --- a/src/webgpu/shader/validation/uniformity/uniformity.spec.ts +++ b/src/webgpu/shader/validation/uniformity/uniformity.spec.ts @@ -4,6 +4,7 @@ import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { keysOf } from '../../../../common/util/data_tables.js'; import { unreachable } from '../../../../common/util/util.js'; import { WGSLLanguageFeature } from '../../../capability_info.js'; +import { skipIfImmediateDataNotSupported } from '../decl/util.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; import { Snippet, LoopCase, compileShouldSucceed } from './snippet.js'; @@ -41,6 +42,7 @@ const kConditions = [ { cond: 'uniform_override', expectation: true }, { cond: 'uniform_let', expectation: true }, { cond: 'nonuniform_let', expectation: false }, + { cond: 'uniform_immediate', expectation: true }, { cond: 'uniform_or', expectation: true }, { cond: 'nonuniform_or1', expectation: false }, { cond: 'nonuniform_or2', expectation: false }, @@ -82,6 +84,9 @@ function generateCondition(condition: string): string { case 'nonuniform_let': { return `n_let == 0`; } + case 'uniform_immediate': { + return `immediate_value == 0u`; + } case 'uniform_or': { return `u_let == 0 || uniform_buffer.y > 1`; } @@ -468,8 +473,13 @@ g.test('basics') if (t.params.op === 'textureBarrier' || t.params.cond.startsWith('storage_texture')) { t.skipIfLanguageFeatureNotSupported('readonly_and_readwrite_storage_textures'); } + const needsImmediate = t.params.cond === 'uniform_immediate'; + if (needsImmediate) { + skipIfImmediateDataNotSupported(t); + } let code = ` + ${needsImmediate ? 'requires immediate_address_space;' : ''} @group(0) @binding(0) var s : sampler; @group(0) @binding(1) var s_comp : sampler_comparison; @group(0) @binding(2) var tex : texture_2d; @@ -478,6 +488,7 @@ g.test('basics') @group(1) @binding(0) var ro_buffer : array; @group(1) @binding(1) var rw_buffer : array; @group(1) @binding(2) var uniform_buffer : vec4; + ${needsImmediate ? 'var immediate_value : u32;' : ''} @group(2) @binding(0) var ro_storage_texture : texture_storage_2d; @group(2) @binding(1) var rw_storage_texture : texture_storage_2d; @@ -566,8 +577,14 @@ g.test('basics,subgroups') .combine('stage', ['compute', 'fragment'] as const) ) .fn(t => { + const needsImmediate = t.params.cond === 'uniform_immediate'; + if (needsImmediate) { + skipIfImmediateDataNotSupported(t); + } + let code = ` enable subgroups; + ${needsImmediate ? 'requires immediate_address_space;' : ''} @group(0) @binding(0) var s : sampler; @group(0) @binding(1) var s_comp : sampler_comparison; @@ -577,6 +594,7 @@ g.test('basics,subgroups') @group(1) @binding(0) var ro_buffer : array; @group(1) @binding(1) var rw_buffer : array; @group(1) @binding(2) var uniform_buffer : vec4; + ${needsImmediate ? 'var immediate_value : u32;' : ''} @group(2) @binding(0) var ro_storage_texture : texture_storage_2d; @group(2) @binding(1) var rw_storage_texture : texture_storage_2d;