From 0ad72a6e701d1cdddd5f7d7ff91daef90fd2fec2 Mon Sep 17 00:00:00 2001 From: James Price Date: Mon, 11 Mar 2024 16:38:20 -0400 Subject: [PATCH] wgsl: Add logical negation validation tests (#3473) Test that the logical negation operator is only accepted for bool scalar and vector types. --- src/webgpu/listing_meta.json | 2 + .../expression/unary/logical_negation.spec.ts | 114 ++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 src/webgpu/shader/validation/expression/unary/logical_negation.spec.ts diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index c752ba6e467a..214c81844eda 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -1939,6 +1939,8 @@ "webgpu:shader,validation,expression,unary,address_of_and_indirection:basic:*": { "subcaseMS": 0.000 }, "webgpu:shader,validation,expression,unary,address_of_and_indirection:composite:*": { "subcaseMS": 0.000 }, "webgpu:shader,validation,expression,unary,address_of_and_indirection:invalid:*": { "subcaseMS": 0.000 }, + "webgpu:shader,validation,expression,unary,logical_negation:invalid_types:*": { "subcaseMS": 7.100 }, + "webgpu:shader,validation,expression,unary,logical_negation:scalar_vector:*": { "subcaseMS": 84.680 }, "webgpu:shader,validation,extension,pointer_composite_access:deref:*": { "subcaseMS": 0.000 }, "webgpu:shader,validation,extension,pointer_composite_access:pointer:*": { "subcaseMS": 0.000 }, "webgpu:shader,validation,extension,readonly_and_readwrite_storage_textures:textureBarrier:*": { "subcaseMS": 1.141 }, diff --git a/src/webgpu/shader/validation/expression/unary/logical_negation.spec.ts b/src/webgpu/shader/validation/expression/unary/logical_negation.spec.ts new file mode 100644 index 000000000000..eda5e224dfd4 --- /dev/null +++ b/src/webgpu/shader/validation/expression/unary/logical_negation.spec.ts @@ -0,0 +1,114 @@ +export const description = ` +Validation tests for logical negation expressions. +`; + +import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { keysOf, objectsToRecord } from '../../../../../common/util/data_tables.js'; +import { kAllScalarsAndVectors, scalarTypeOf, Type } from '../../../../util/conversion.js'; +import { ShaderValidationTest } from '../../shader_validation_test.js'; + +export const g = makeTestGroup(ShaderValidationTest); + +// A list of scalar and vector types. +const kScalarAndVectorTypes = objectsToRecord(kAllScalarsAndVectors); + +g.test('scalar_vector') + .desc( + ` + Validates that scalar and vector logical negation expressions are only accepted for bool types. + ` + ) + .params(u => u.combine('type', keysOf(kScalarAndVectorTypes)).beginSubcases()) + .beforeAllSubcases(t => { + if (scalarTypeOf(kScalarAndVectorTypes[t.params.type]) === Type.f16) { + t.selectDeviceOrSkipTestCase('shader-f16'); + } + }) + .fn(t => { + const type = kScalarAndVectorTypes[t.params.type]; + const elementTy = scalarTypeOf(type); + const hasF16 = elementTy === Type.f16; + const code = ` +${hasF16 ? 'enable f16;' : ''} +const rhs = ${type.create(elementTy.kind === 'abstract-int' ? 0n : 0).wgsl()}; +const foo = !rhs; +`; + + t.expectCompileResult(elementTy === Type.bool, code); + }); + +interface InvalidTypeConfig { + // An expression that produces a value of the target type. + expr: string; + // A function that converts an expression of the target type into a valid negation operand. + control: (x: string) => string; +} +const kInvalidTypes: Record = { + mat2x2f: { + expr: 'm', + control: e => `bool(${e}[0][0])`, + }, + + array: { + expr: 'arr', + control: e => `${e}[0]`, + }, + + ptr: { + expr: '(&b)', + control: e => `*${e}`, + }, + + atomic: { + expr: 'a', + control: e => `bool(atomicLoad(&${e}))`, + }, + + texture: { + expr: 't', + control: e => `bool(textureLoad(${e}, vec2(), 0).x)`, + }, + + sampler: { + expr: 's', + control: e => `bool(textureSampleLevel(t, ${e}, vec2(), 0).x)`, + }, + + struct: { + expr: 'str', + control: e => `${e}.b`, + }, +}; + +g.test('invalid_types') + .desc( + ` + Validates that logical negation expressions are never accepted for non-scalar and non-vector types. + ` + ) + .params(u => + u.combine('type', keysOf(kInvalidTypes)).combine('control', [true, false]).beginSubcases() + ) + .fn(t => { + const type = kInvalidTypes[t.params.type]; + const expr = t.params.control ? type.control(type.expr) : type.expr; + const code = ` +@group(0) @binding(0) var t : texture_2d; +@group(0) @binding(1) var s : sampler; +@group(0) @binding(2) var a : atomic; + +struct S { b : bool } + +var b : bool; +var m : mat2x2f; +var arr : array; +var str : S; + +@compute @workgroup_size(1) +fn main() { + let foo = !${expr}; +} +`; + + t.expectCompileResult(t.params.control, code); + });