From 6c58a195839034d9f72bdc125cfe8dabcce7336d Mon Sep 17 00:00:00 2001 From: James Price Date: Tue, 23 Jul 2024 15:29:06 -0400 Subject: [PATCH] wgsl: Add coverage for swizzle on a pointer (#3869) * wgsl: Add coverage for swizzle on a pointer In addition to a new execution test, also add coverage to the alias analysis and uniformity analysis tests. Both of these new tests failed prior to a recent Tint change that fixed a bug with these swizzles. * Change for review * Use skipIf for execution test * Add uniform version of swizzle uniformity test --- src/webgpu/listing_meta.json | 2 + .../unary/address_of_and_indirection.spec.ts | 66 +++++++++++++++---- .../functions/alias_analysis.spec.ts | 36 ++++++++++ .../validation/uniformity/uniformity.spec.ts | 15 +++++ 4 files changed, 105 insertions(+), 14 deletions(-) diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index 4708660ab4a9..272b97a69d29 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -1654,6 +1654,7 @@ "webgpu:shader,execution,expression,unary,address_of_and_indirection:deref:*": { "subcaseMS": 0.000 }, "webgpu:shader,execution,expression,unary,address_of_and_indirection:deref_index:*": { "subcaseMS": 0.000 }, "webgpu:shader,execution,expression,unary,address_of_and_indirection:deref_member:*": { "subcaseMS": 0.000 }, + "webgpu:shader,execution,expression,unary,address_of_and_indirection:deref_swizzle:*": { "subcaseMS": 821.056 }, "webgpu:shader,execution,expression,unary,af_arithmetic:negation:*": { "subcaseMS": 2165.950 }, "webgpu:shader,execution,expression,unary,af_assignment:abstract:*": { "subcaseMS": 788.400 }, "webgpu:shader,execution,expression,unary,af_assignment:f16:*": { "subcaseMS": 1.000 }, @@ -2476,6 +2477,7 @@ "webgpu:shader,validation,functions,alias_analysis:one_pointer_one_module_scope:*": { "subcaseMS": 1.598 }, "webgpu:shader,validation,functions,alias_analysis:same_pointer_read_and_write:*": { "subcaseMS": 1.301 }, "webgpu:shader,validation,functions,alias_analysis:subcalls:*": { "subcaseMS": 1.673 }, + "webgpu:shader,validation,functions,alias_analysis:swizzles:*": { "subcaseMS": 7.188 }, "webgpu:shader,validation,functions,alias_analysis:two_atomic_pointers:*": { "subcaseMS": 0.000 }, "webgpu:shader,validation,functions,alias_analysis:two_atomic_pointers_to_array_elements:*": { "subcaseMS": 0.000 }, "webgpu:shader,validation,functions,alias_analysis:two_atomic_pointers_to_struct_members:*": { "subcaseMS": 0.000 }, diff --git a/src/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.ts b/src/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.ts index c4961558e0c2..bdce7870ddad 100644 --- a/src/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.ts +++ b/src/webgpu/shader/execution/expression/unary/address_of_and_indirection.spec.ts @@ -95,15 +95,12 @@ Pointer expression dereference as lhs of index accessor expression if (t.params.scalarType === 'f16') { t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); } + t.skipIf( + kDerefCases[t.params.derefType].requires_pointer_composite_access && + !t.hasLanguageFeature('pointer_composite_access') + ); }) .fn(async t => { - if ( - kDerefCases[t.params.derefType].requires_pointer_composite_access && - !t.hasLanguageFeature('pointer_composite_access') - ) { - return; - } - const ty = scalarType(t.params.scalarType); const cases = sparseScalarF32Range().map(e => { return { input: ty.create(e), expected: ty.create(e) }; @@ -141,15 +138,12 @@ Pointer expression dereference as lhs of member accessor expression if (t.params.scalarType === 'f16') { t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); } + t.skipIf( + kDerefCases[t.params.derefType].requires_pointer_composite_access && + !t.hasLanguageFeature('pointer_composite_access') + ); }) .fn(async t => { - if ( - kDerefCases[t.params.derefType].requires_pointer_composite_access && - !t.hasLanguageFeature('pointer_composite_access') - ) { - return; - } - const ty = scalarType(t.params.scalarType); const cases = sparseScalarF32Range().map(e => { return { input: ty.create(e), expected: ty.create(e) }; @@ -169,3 +163,47 @@ Pointer expression dereference as lhs of member accessor expression ); await run(t, shaderBuilder, [ty], ty, t.params, cases); }); + +g.test('deref_swizzle') + .specURL('https://www.w3.org/TR/WGSL/#logical-expr') + .desc( + ` +Expression: (*e).swizzle + +Pointer expression dereference as lhs of swizzle expression +` + ) + .params(u => + u + .combine('inputSource', allButConstInputSource) + .combine('vectorize', [2, 3, 4] as const) + .combine('scalarType', ['bool', 'u32', 'i32', 'f32', 'f16'] as ScalarKind[]) + .combine('derefType', keysOf(kDerefCases)) + ) + .beforeAllSubcases(t => { + if (t.params.scalarType === 'f16') { + t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] }); + } + t.skipIf( + kDerefCases[t.params.derefType].requires_pointer_composite_access && + !t.hasLanguageFeature('pointer_composite_access') + ); + }) + .fn(async t => { + const ty = scalarType(t.params.scalarType); + const cases = sparseScalarF32Range().map(e => { + return { input: ty.create(e), expected: ty.create(e) }; + }); + const elemType = ty.kind; + const type = `vec${t.params.vectorize}<${elemType}>`; + const swizzle = 'xyzw'.slice(0, t.params.vectorize); + const shaderBuilder = basicExpressionWithPredeclarationBuilder( + value => `get_dereferenced_value(${value})`, + `fn get_dereferenced_value(value: ${type}) -> ${type} { + var a = value; + let p = &a; + return ${kDerefCases[t.params.derefType].wgsl}.${swizzle}; + }` + ); + await run(t, shaderBuilder, [ty], ty, t.params, cases); + }); diff --git a/src/webgpu/shader/validation/functions/alias_analysis.spec.ts b/src/webgpu/shader/validation/functions/alias_analysis.spec.ts index 7efad7e7981f..b428e4ee9584 100644 --- a/src/webgpu/shader/validation/functions/alias_analysis.spec.ts +++ b/src/webgpu/shader/validation/functions/alias_analysis.spec.ts @@ -409,6 +409,42 @@ fn caller() { t.expectCompileResult(shouldPass(t.params.aliased, t.params.a_use, t.params.b_use), code); }); +g.test('swizzles') + .desc(`Test aliasing of two pointers passed to a function and used with swizzles.`) + .params(u => + u + .combine('address_space', ['private', 'storage', 'workgroup'] as const) + .combine('aliased', [true, false]) + .beginSubcases() + .combine('a_use', ['no_access', 'compound_assign_lhs'] as UseName[]) + .combine('deref', [true, false]) + ) + .fn(t => { + if (requiresUnrestrictedPointerParameters(t.params.address_space)) { + t.skipIfLanguageFeatureNotSupported('unrestricted_pointer_parameters'); + } + if (t.params.deref === false) { + t.skipIfLanguageFeatureNotSupported('pointer_composite_access'); + } + + const ptr_vec = ptr(t.params.address_space, 'vec4i'); + const code = ` +${declareModuleScopeVar('x', t.params.address_space, 'vec4i')} +${declareModuleScopeVar('y', t.params.address_space, 'vec4i')} + +fn callee(pa : ${ptr_vec}, pb : ${ptr_vec}) -> i32 { + ${kUses[t.params.a_use].gen(`(*pa)`)} + let value = ${t.params.deref ? `(*pb)` : `pb`}.wzyx; + return 0; +} + +fn caller() { + callee(&x, ${t.params.aliased ? `&x` : `&y`}); +} +`; + t.expectCompileResult(shouldPass(t.params.aliased, t.params.a_use, 'let_init'), code); + }); + g.test('same_pointer_read_and_write') .desc(`Test that we can read from and write to the same pointer.`) .params(u => diff --git a/src/webgpu/shader/validation/uniformity/uniformity.spec.ts b/src/webgpu/shader/validation/uniformity/uniformity.spec.ts index 27ae7257a7de..31d7f9048d6a 100644 --- a/src/webgpu/shader/validation/uniformity/uniformity.spec.ts +++ b/src/webgpu/shader/validation/uniformity/uniformity.spec.ts @@ -777,6 +777,20 @@ const kPointerCases: Record = { uniform: `never`, needs_deref_sugar: true, }, + contents_rhs_pointer_swizzle_uniform: { + code: `func_vector = vec4(uniform_value); + let test_val = dot((&func_vector).yw, vec2());`, + check: `contents`, + uniform: true, + needs_deref_sugar: true, + }, + contents_rhs_pointer_swizzle_non_uniform: { + code: `func_vector = vec4(nonuniform_value); + let test_val = dot((&func_vector).yw, vec2());`, + check: `contents`, + uniform: false, + needs_deref_sugar: true, + }, }; g.test('pointers') @@ -815,6 +829,7 @@ fn needs_uniform(val : u32) -> u32{ fn main(@builtin(local_invocation_id) lid : vec3, @builtin(global_invocation_id) gid : vec3) { var func_scalar : u32; + var func_vector : vec4u; var func_array : array; var func_struct : Outer;