diff --git a/src/resources/cache/hashes.json b/src/resources/cache/hashes.json index 5cca979a570a..27945b7a4a71 100644 --- a/src/resources/cache/hashes.json +++ b/src/resources/cache/hashes.json @@ -1,107 +1,109 @@ { - "webgpu/shader/execution/binary/af_addition.bin": "8d0f30f7", - "webgpu/shader/execution/binary/af_logical.bin": "6f90d890", - "webgpu/shader/execution/binary/af_division.bin": "62bb30ee", - "webgpu/shader/execution/binary/af_matrix_addition.bin": "ffcf0ff6", - "webgpu/shader/execution/binary/af_matrix_subtraction.bin": "93e789f4", - "webgpu/shader/execution/binary/af_multiplication.bin": "fb0289ae", - "webgpu/shader/execution/binary/af_remainder.bin": "d6498bff", - "webgpu/shader/execution/binary/af_subtraction.bin": "f5a08d60", - "webgpu/shader/execution/binary/f16_addition.bin": "a6b5ed00", - "webgpu/shader/execution/binary/f16_logical.bin": "d4267b82", - "webgpu/shader/execution/binary/f16_division.bin": "b2a99359", - "webgpu/shader/execution/binary/f16_matrix_addition.bin": "c283fb3e", - "webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "62c8af83", - "webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "7b1745df", - "webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "81aaa2af", - "webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "effb48b4", - "webgpu/shader/execution/binary/f16_multiplication.bin": "514e3fd6", - "webgpu/shader/execution/binary/f16_remainder.bin": "3b28785e", - "webgpu/shader/execution/binary/f16_subtraction.bin": "bcd36671", - "webgpu/shader/execution/binary/f32_addition.bin": "f0bba966", - "webgpu/shader/execution/binary/f32_logical.bin": "673ceb6f", - "webgpu/shader/execution/binary/f32_division.bin": "3be818fd", - "webgpu/shader/execution/binary/f32_matrix_addition.bin": "9959f181", - "webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "40e03a0b", - "webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "9e3271b4", - "webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "3391a792", - "webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "b06af5df", - "webgpu/shader/execution/binary/f32_multiplication.bin": "e417c2ad", - "webgpu/shader/execution/binary/f32_remainder.bin": "c81d1149", - "webgpu/shader/execution/binary/f32_subtraction.bin": "e24bccfb", - "webgpu/shader/execution/binary/i32_arithmetic.bin": "77c30f31", - "webgpu/shader/execution/binary/i32_comparison.bin": "acb55d71", - "webgpu/shader/execution/binary/u32_arithmetic.bin": "8c21844", - "webgpu/shader/execution/binary/u32_comparison.bin": "47006c1e", - "webgpu/shader/execution/abs.bin": "609c82f5", - "webgpu/shader/execution/acos.bin": "5a5119aa", - "webgpu/shader/execution/acosh.bin": "b8678003", - "webgpu/shader/execution/asin.bin": "a3699bc", - "webgpu/shader/execution/asinh.bin": "d4e7d221", - "webgpu/shader/execution/atan.bin": "89581e73", - "webgpu/shader/execution/atan2.bin": "60de18cf", - "webgpu/shader/execution/atanh.bin": "25f3bf40", - "webgpu/shader/execution/bitcast.bin": "55637893", - "webgpu/shader/execution/ceil.bin": "7387e75d", - "webgpu/shader/execution/clamp.bin": "ec485cef", - "webgpu/shader/execution/cos.bin": "5936a955", - "webgpu/shader/execution/cosh.bin": "c34185a7", - "webgpu/shader/execution/cross.bin": "47741063", - "webgpu/shader/execution/degrees.bin": "4732b47", - "webgpu/shader/execution/determinant.bin": "fa978d0c", - "webgpu/shader/execution/distance.bin": "5729aae8", - "webgpu/shader/execution/dot.bin": "ba6b9056", - "webgpu/shader/execution/exp.bin": "f35017fd", - "webgpu/shader/execution/exp2.bin": "49d0add6", - "webgpu/shader/execution/faceForward.bin": "aa5ad639", - "webgpu/shader/execution/floor.bin": "f6918e48", - "webgpu/shader/execution/fma.bin": "58287b5a", - "webgpu/shader/execution/fract.bin": "e4575525", - "webgpu/shader/execution/frexp.bin": "279c7c5c", - "webgpu/shader/execution/inverseSqrt.bin": "748c6766", - "webgpu/shader/execution/ldexp.bin": "a7fb97ac", - "webgpu/shader/execution/length.bin": "93dcf7f8", - "webgpu/shader/execution/log.bin": "112fbabe", - "webgpu/shader/execution/log2.bin": "2da3da02", - "webgpu/shader/execution/max.bin": "51bdd68f", - "webgpu/shader/execution/min.bin": "7b207776", - "webgpu/shader/execution/mix.bin": "9b7c2c7c", - "webgpu/shader/execution/modf.bin": "7219e40e", - "webgpu/shader/execution/normalize.bin": "14a04a26", - "webgpu/shader/execution/pack2x16float.bin": "37c8eb38", - "webgpu/shader/execution/pow.bin": "ac8520ee", - "webgpu/shader/execution/quantizeToF16.bin": "9252e236", - "webgpu/shader/execution/radians.bin": "5b50053b", - "webgpu/shader/execution/reflect.bin": "5699ed6b", - "webgpu/shader/execution/refract.bin": "3f78b15b", - "webgpu/shader/execution/round.bin": "94c7bef5", - "webgpu/shader/execution/saturate.bin": "90c116dd", - "webgpu/shader/execution/sign.bin": "520aeb67", - "webgpu/shader/execution/sin.bin": "8ea07595", - "webgpu/shader/execution/sinh.bin": "d1def282", - "webgpu/shader/execution/smoothstep.bin": "639ea26f", - "webgpu/shader/execution/sqrt.bin": "78bf8dac", - "webgpu/shader/execution/step.bin": "8187b37a", - "webgpu/shader/execution/tan.bin": "2fb1b66f", - "webgpu/shader/execution/tanh.bin": "76b7e183", - "webgpu/shader/execution/transpose.bin": "c8906ac0", - "webgpu/shader/execution/trunc.bin": "22fda1bd", - "webgpu/shader/execution/unpack2x16float.bin": "980ea3a8", - "webgpu/shader/execution/unpack2x16snorm.bin": "6a181f0b", - "webgpu/shader/execution/unpack2x16unorm.bin": "aeabbab9", - "webgpu/shader/execution/unpack4x8snorm.bin": "c8460176", - "webgpu/shader/execution/unpack4x8unorm.bin": "30b9abb3", - "webgpu/shader/execution/unary/af_arithmetic.bin": "3119c00e", - "webgpu/shader/execution/unary/af_assignment.bin": "bbdefb2", - "webgpu/shader/execution/unary/bool_conversion.bin": "70c51822", - "webgpu/shader/execution/unary/f16_arithmetic.bin": "8d1065e0", - "webgpu/shader/execution/unary/f16_conversion.bin": "944968d0", - "webgpu/shader/execution/unary/f32_arithmetic.bin": "efb7b8b9", - "webgpu/shader/execution/unary/f32_conversion.bin": "ee857943", - "webgpu/shader/execution/unary/i32_arithmetic.bin": "cc125c13", - "webgpu/shader/execution/unary/i32_conversion.bin": "fb4402f9", - "webgpu/shader/execution/unary/u32_conversion.bin": "579a043f", - "webgpu/shader/execution/unary/ai_assignment.bin": "954223ff", - "webgpu/shader/execution/binary/ai_arithmetic.bin": "6c440be0", - "webgpu/shader/execution/unary/ai_arithmetic.bin": "e89e9e9" + "webgpu/shader/execution/binary/af_addition.bin": "5067132e", + "webgpu/shader/execution/binary/af_logical.bin": "a7bde13e", + "webgpu/shader/execution/binary/af_division.bin": "19678742", + "webgpu/shader/execution/binary/af_matrix_addition.bin": "42689934", + "webgpu/shader/execution/binary/af_matrix_subtraction.bin": "c6322f74", + "webgpu/shader/execution/binary/af_multiplication.bin": "5f12d793", + "webgpu/shader/execution/binary/af_remainder.bin": "df05ecb8", + "webgpu/shader/execution/binary/af_subtraction.bin": "a13ed62f", + "webgpu/shader/execution/binary/f16_addition.bin": "14e49495", + "webgpu/shader/execution/binary/f16_logical.bin": "9e733738", + "webgpu/shader/execution/binary/f16_division.bin": "f42b09dc", + "webgpu/shader/execution/binary/f16_matrix_addition.bin": "517b60f1", + "webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "66a87207", + "webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "a9c3e5f1", + "webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "f2a25933", + "webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "a886a0b5", + "webgpu/shader/execution/binary/f16_multiplication.bin": "be77033b", + "webgpu/shader/execution/binary/f16_remainder.bin": "50b0b02", + "webgpu/shader/execution/binary/f16_subtraction.bin": "93f65d9", + "webgpu/shader/execution/binary/f32_addition.bin": "278d2454", + "webgpu/shader/execution/binary/f32_logical.bin": "55bcf58e", + "webgpu/shader/execution/binary/f32_division.bin": "3a457201", + "webgpu/shader/execution/binary/f32_matrix_addition.bin": "660aad6a", + "webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "a278509a", + "webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "ace2da73", + "webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "8f986eff", + "webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "c26e2700", + "webgpu/shader/execution/binary/f32_multiplication.bin": "4cdfcb27", + "webgpu/shader/execution/binary/f32_remainder.bin": "e3119b6d", + "webgpu/shader/execution/binary/f32_subtraction.bin": "d71a5a86", + "webgpu/shader/execution/binary/i32_arithmetic.bin": "b880610d", + "webgpu/shader/execution/binary/i32_comparison.bin": "f2f668b2", + "webgpu/shader/execution/binary/u32_arithmetic.bin": "164ebf51", + "webgpu/shader/execution/binary/u32_comparison.bin": "35a31af1", + "webgpu/shader/execution/abs.bin": "ec6cc570", + "webgpu/shader/execution/acos.bin": "d61bb028", + "webgpu/shader/execution/acosh.bin": "609af763", + "webgpu/shader/execution/asin.bin": "64bf727b", + "webgpu/shader/execution/asinh.bin": "273b8028", + "webgpu/shader/execution/atan.bin": "f6384fbb", + "webgpu/shader/execution/atan2.bin": "64163f99", + "webgpu/shader/execution/atanh.bin": "bacbfd59", + "webgpu/shader/execution/bitcast.bin": "4a0d7d41", + "webgpu/shader/execution/ceil.bin": "48020ceb", + "webgpu/shader/execution/clamp.bin": "402bf6c9", + "webgpu/shader/execution/cos.bin": "6b4d2358", + "webgpu/shader/execution/cosh.bin": "dccbe75f", + "webgpu/shader/execution/cross.bin": "a550a630", + "webgpu/shader/execution/degrees.bin": "72d5163b", + "webgpu/shader/execution/determinant.bin": "f1378c53", + "webgpu/shader/execution/distance.bin": "48ee3f00", + "webgpu/shader/execution/dot.bin": "d2f81d75", + "webgpu/shader/execution/exp.bin": "36af62ed", + "webgpu/shader/execution/exp2.bin": "8675703d", + "webgpu/shader/execution/faceForward.bin": "568cc6b8", + "webgpu/shader/execution/floor.bin": "e7ab0a1e", + "webgpu/shader/execution/fma.bin": "3b4ebf3f", + "webgpu/shader/execution/fract.bin": "130ceb8a", + "webgpu/shader/execution/frexp.bin": "a5868197", + "webgpu/shader/execution/inverseSqrt.bin": "e2a63a07", + "webgpu/shader/execution/ldexp.bin": "62948ba1", + "webgpu/shader/execution/length.bin": "ce1440e5", + "webgpu/shader/execution/log.bin": "69b69fa1", + "webgpu/shader/execution/log2.bin": "dc5c999d", + "webgpu/shader/execution/max.bin": "58fc2b9a", + "webgpu/shader/execution/min.bin": "84eec3dd", + "webgpu/shader/execution/mix.bin": "8c176bc2", + "webgpu/shader/execution/modf.bin": "9fcb3629", + "webgpu/shader/execution/normalize.bin": "4bf45f2a", + "webgpu/shader/execution/pack2x16float.bin": "74aac2f5", + "webgpu/shader/execution/pow.bin": "976aaac6", + "webgpu/shader/execution/quantizeToF16.bin": "9b60dec9", + "webgpu/shader/execution/radians.bin": "f37fa7ad", + "webgpu/shader/execution/reflect.bin": "d0da3a14", + "webgpu/shader/execution/refract.bin": "f426dd6e", + "webgpu/shader/execution/round.bin": "ffc365ff", + "webgpu/shader/execution/saturate.bin": "253ffcc7", + "webgpu/shader/execution/sign.bin": "ee72deed", + "webgpu/shader/execution/sin.bin": "c685df75", + "webgpu/shader/execution/sinh.bin": "404bade3", + "webgpu/shader/execution/smoothstep.bin": "4631743e", + "webgpu/shader/execution/sqrt.bin": "29d895f1", + "webgpu/shader/execution/step.bin": "e246e2ed", + "webgpu/shader/execution/tan.bin": "37d5e55c", + "webgpu/shader/execution/tanh.bin": "4964f0af", + "webgpu/shader/execution/transpose.bin": "c0688654", + "webgpu/shader/execution/trunc.bin": "29a4bedf", + "webgpu/shader/execution/unpack2x16float.bin": "45a53d8d", + "webgpu/shader/execution/unpack2x16snorm.bin": "827b024f", + "webgpu/shader/execution/unpack2x16unorm.bin": "dc1bd85a", + "webgpu/shader/execution/unpack4x8snorm.bin": "f9525320", + "webgpu/shader/execution/unpack4x8unorm.bin": "27facc7f", + "webgpu/shader/execution/unary/af_arithmetic.bin": "213bf535", + "webgpu/shader/execution/unary/af_assignment.bin": "7d092411", + "webgpu/shader/execution/unary/bool_conversion.bin": "ef64f29e", + "webgpu/shader/execution/unary/f16_arithmetic.bin": "e7a930c", + "webgpu/shader/execution/unary/f16_conversion.bin": "ed0ad482", + "webgpu/shader/execution/unary/f32_arithmetic.bin": "e32dcdbd", + "webgpu/shader/execution/unary/f32_conversion.bin": "b0b23a1a", + "webgpu/shader/execution/unary/i32_arithmetic.bin": "5a180128", + "webgpu/shader/execution/unary/i32_complement.bin": "7266637b", + "webgpu/shader/execution/unary/i32_conversion.bin": "5f788044", + "webgpu/shader/execution/unary/u32_complement.bin": "44efa30e", + "webgpu/shader/execution/unary/u32_conversion.bin": "d9aec403", + "webgpu/shader/execution/unary/ai_assignment.bin": "cb574671", + "webgpu/shader/execution/binary/ai_arithmetic.bin": "9c9ef2a4", + "webgpu/shader/execution/unary/ai_arithmetic.bin": "6fadb5ac" } \ No newline at end of file diff --git a/src/resources/cache/webgpu/shader/execution/bitcast.bin b/src/resources/cache/webgpu/shader/execution/bitcast.bin index ab435f3902a6..d3954903ac89 100644 Binary files a/src/resources/cache/webgpu/shader/execution/bitcast.bin and b/src/resources/cache/webgpu/shader/execution/bitcast.bin differ diff --git a/src/resources/cache/webgpu/shader/execution/dot.bin b/src/resources/cache/webgpu/shader/execution/dot.bin index 09c884bde8c3..9783146bff44 100644 Binary files a/src/resources/cache/webgpu/shader/execution/dot.bin and b/src/resources/cache/webgpu/shader/execution/dot.bin differ diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index e5cbb483c0c8..2730fbe84a73 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -1254,7 +1254,9 @@ "webgpu:shader,execution,expression,call,builtin,dot4I8Packed:basic:*": { "subcaseMS": 1.000 }, "webgpu:shader,execution,expression,call,builtin,dot4U8Packed:basic:*": { "subcaseMS": 1.000 }, "webgpu:shader,execution,expression,call,builtin,dot:abstract_float:*": { "subcaseMS": 8.902 }, - "webgpu:shader,execution,expression,call,builtin,dot:abstract_int:*": { "subcaseMS": 2.902 }, + "webgpu:shader,execution,expression,call,builtin,dot:abstract_int_vec2:*": { "subcaseMS": 0 }, + "webgpu:shader,execution,expression,call,builtin,dot:abstract_int_vec3:*": { "subcaseMS": 0 }, + "webgpu:shader,execution,expression,call,builtin,dot:abstract_int_vec4:*": { "subcaseMS": 0 }, "webgpu:shader,execution,expression,call,builtin,dot:f16_vec2:*": { "subcaseMS": 981.225 }, "webgpu:shader,execution,expression,call,builtin,dot:f16_vec3:*": { "subcaseMS": 50.350 }, "webgpu:shader,execution,expression,call,builtin,dot:f16_vec4:*": { "subcaseMS": 52.250 }, diff --git a/src/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.ts b/src/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.ts index bb68b8d1c5f9..48300e801302 100644 --- a/src/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.ts +++ b/src/webgpu/shader/execution/expression/binary/ai_arithmetic.cache.ts @@ -7,36 +7,33 @@ import { } from '../case.js'; import { makeCaseCache } from '../case_cache.js'; -function isOOB(val: bigint): boolean { - return val > kValue.i64.positive.max || val < kValue.i64.negative.min; -} function ai_add(x: bigint, y: bigint): bigint | undefined { const result = x + y; - return !isOOB(result) ? result : undefined; + return !kValue.i64.isOOB(result) ? result : undefined; } function ai_div(x: bigint, y: bigint): bigint | undefined { if (y === 0n) return undefined; if (x === kValue.i64.negative.min && y === -1n) return undefined; const result = x / y; - return !isOOB(result) ? result : undefined; + return !kValue.i64.isOOB(result) ? result : undefined; } function ai_mul(x: bigint, y: bigint): bigint | undefined { const result = x * y; - return !isOOB(result) ? result : undefined; + return !kValue.i64.isOOB(result) ? result : undefined; } function ai_rem(x: bigint, y: bigint): bigint | undefined { if (y === 0n) return undefined; if (x === kValue.i64.negative.min && y === -1n) return undefined; const result = x % y; - return !isOOB(result) ? result : undefined; + return !kValue.i64.isOOB(result) ? result : undefined; } function ai_sub(x: bigint, y: bigint): bigint | undefined { const result = x - y; - return !isOOB(result) ? result : undefined; + return !kValue.i64.isOOB(result) ? result : undefined; } export const d = makeCaseCache('binary/ai_arithmetic', { diff --git a/src/webgpu/shader/execution/expression/call/builtin/dot.cache.ts b/src/webgpu/shader/execution/expression/call/builtin/dot.cache.ts index 979e476f85f4..73b78c11d725 100644 --- a/src/webgpu/shader/execution/expression/call/builtin/dot.cache.ts +++ b/src/webgpu/shader/execution/expression/call/builtin/dot.cache.ts @@ -1,8 +1,51 @@ +import { ROArrayArray } from '../../../../../../common/util/types.js'; +import { assert } from '../../../../../../common/util/util.js'; +import { kValue } from '../../../../../util/constants.js'; import { FP } from '../../../../../util/floating_point.js'; +import { + calculatePermutations, + sparseVectorI64Range, + vectorI64Range, +} from '../../../../../util/math.js'; +import { generateVectorVectorToI64Cases } from '../../case.js'; import { makeCaseCache } from '../../case_cache.js'; +function ai_dot(x: bigint[], y: bigint[]): bigint | undefined { + assert(x.length === y.length, 'Cannot calculate dot for vectors of different lengths'); + const multiplications = x.map((_, idx) => x[idx] * y[idx]); + if (multiplications.some(kValue.i64.isOOB)) return undefined; + + const result = multiplications.reduce((prev, curr) => prev + curr); + if (kValue.i64.isOOB(result)) return undefined; + + // The spec does not state the ordering of summation, so all the + // permutations are calculated and the intermediate results checked for + // going OOB. vec2 does not need permutations, since a + b === b + a. + // All the end results should be the same regardless of the order if the + // intermediate additions stay inbounds. + if (x.length !== 2) { + let wentOOB: boolean = false; + const permutations: ROArrayArray = calculatePermutations(multiplications); + permutations.forEach(p => { + if (!wentOOB) { + p.reduce((prev, curr) => { + const next = prev + curr; + if (kValue.i64.isOOB(next)) { + wentOOB = true; + } + return next; + }); + } + }); + + if (wentOOB) return undefined; + } + + return !kValue.i64.isOOB(result) ? result : undefined; +} + // Cases: [f32|f16]_vecN_[non_]const -const cases = (['f32', 'f16'] as const) +const float_cases = (['f32', 'f16'] as const) .flatMap(trait => ([2, 3, 4] as const).flatMap(N => ([true, false] as const).map(nonConst => ({ @@ -21,4 +64,17 @@ const cases = (['f32', 'f16'] as const) ) .reduce((a, b) => ({ ...a, ...b }), {}); +const cases = { + ...float_cases, + abstract_int_vec2: () => { + return generateVectorVectorToI64Cases(vectorI64Range(2), vectorI64Range(2), ai_dot); + }, + abstract_int_vec3: () => { + return generateVectorVectorToI64Cases(sparseVectorI64Range(3), sparseVectorI64Range(3), ai_dot); + }, + abstract_int_vec4: () => { + return generateVectorVectorToI64Cases(sparseVectorI64Range(4), sparseVectorI64Range(4), ai_dot); + }, +}; + export const d = makeCaseCache('dot', cases); diff --git a/src/webgpu/shader/execution/expression/call/builtin/dot.spec.ts b/src/webgpu/shader/execution/expression/call/builtin/dot.spec.ts index 215f3879dc2e..6e9eb18b558e 100644 --- a/src/webgpu/shader/execution/expression/call/builtin/dot.spec.ts +++ b/src/webgpu/shader/execution/expression/call/builtin/dot.spec.ts @@ -8,19 +8,61 @@ Returns the dot product of e1 and e2. import { makeTestGroup } from '../../../../../../common/framework/test_group.js'; import { GPUTest } from '../../../../../gpu_test.js'; -import { TypeF16, TypeF32, TypeVec } from '../../../../../util/conversion.js'; -import { allInputSources, run } from '../../expression.js'; +import { TypeAbstractInt, TypeF16, TypeF32, TypeVec } from '../../../../../util/conversion.js'; +import { allInputSources, onlyConstInputSource, run } from '../../expression.js'; -import { builtin } from './builtin.js'; +import { abstractIntBuiltin, builtin } from './builtin.js'; import { d } from './dot.cache.js'; export const g = makeTestGroup(GPUTest); -g.test('abstract_int') +g.test('abstract_int_vec2') .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions') - .desc(`abstract int tests`) - .params(u => u.combine('inputSource', allInputSources)) - .unimplemented(); + .desc(`abstract float tests using vec2s`) + .params(u => u.combine('inputSource', onlyConstInputSource)) + .fn(async t => { + const cases = await d.get('abstract_int_vec2'); + await run( + t, + abstractIntBuiltin('dot'), + [TypeVec(2, TypeAbstractInt), TypeVec(2, TypeAbstractInt)], + TypeAbstractInt, + t.params, + cases + ); + }); + +g.test('abstract_int_vec3') + .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions') + .desc(`abstract float tests using vec3s`) + .params(u => u.combine('inputSource', onlyConstInputSource)) + .fn(async t => { + const cases = await d.get('abstract_int_vec3'); + await run( + t, + abstractIntBuiltin('dot'), + [TypeVec(3, TypeAbstractInt), TypeVec(3, TypeAbstractInt)], + TypeAbstractInt, + t.params, + cases + ); + }); + +g.test('abstract_int_vec4') + .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions') + .desc(`abstract float tests using vec4s`) + .params(u => u.combine('inputSource', onlyConstInputSource)) + .fn(async t => { + const cases = await d.get('abstract_int_vec4'); + await run( + t, + abstractIntBuiltin('dot'), + [TypeVec(4, TypeAbstractInt), TypeVec(4, TypeAbstractInt)], + TypeAbstractInt, + t.params, + cases + ); + }); g.test('i32') .specURL('https://www.w3.org/TR/WGSL/#vector-builtin-functions') diff --git a/src/webgpu/shader/execution/expression/case.ts b/src/webgpu/shader/execution/expression/case.ts index b765e48eba17..1f79b003a833 100644 --- a/src/webgpu/shader/execution/expression/case.ts +++ b/src/webgpu/shader/execution/expression/case.ts @@ -33,6 +33,14 @@ export interface BinaryOp { (x: T, y: T): T | undefined; } +/** + * A function that performs a vector-vector operation on x and y, and returns the + * expected result. + */ +export interface VectorVectorToScalarOp { + (x: T[], y: T[]): T | undefined; +} + /** * @returns a Case for the input params with op applied * @param scalar scalar param @@ -286,3 +294,70 @@ export function generateBinaryToI64Cases( ) { return generateScalarBinaryToScalarCases(param0s, param1s, op, quantizeToI64, abstractInt); } + +/** + * @returns a Case for the input params with op applied + * @param param0 vector param (2, 3, or 4 elements) for the first param + * @param param1 vector param (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function makeVectorVectorToScalarCase( + param0: readonly T[], + param1: readonly T[], + op: VectorVectorToScalarOp, + quantize: QuantizeFunc, + scalarize: ScalarBuilder +): Case | undefined { + const param0_quantized = param0.map(quantize); + const param1_quantized = param1.map(quantize); + const result = op(param0_quantized, param1_quantized); + if (result === undefined) return undefined; + + return { + input: [ + new Vector(param0_quantized.map(scalarize)), + new Vector(param1_quantized.map(scalarize)), + ], + expected: scalarize(result), + }; +} + +/** + * @returns array of Case for the input params with op applied + * @param param0s array of vector params (2, 3, or 4 elements) for the first param + * @param param1s array of vector params (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + * @param quantize function to quantize all values in vectors and scalars + * @param scalarize function to convert numbers to Scalars + */ +function generateVectorVectorToScalarCases( + param0s: ROArrayArray, + param1s: ROArrayArray, + op: VectorVectorToScalarOp, + quantize: QuantizeFunc, + scalarize: ScalarBuilder +): Case[] { + return param0s.flatMap(param0 => { + return param1s + .map(param1 => { + return makeVectorVectorToScalarCase(param0, param1, op, quantize, scalarize); + }) + .filter(notUndefined); + }); +} + +/** + * @returns array of Case for the input params with op applied + * @param param0s array of vector params (2, 3, or 4 elements) for the first param + * @param param1s array of vector params (2, 3, or 4 elements) for the second param + * @param op the op to apply to each pair of vectors + */ +export function generateVectorVectorToI64Cases( + param0s: ROArrayArray, + param1s: ROArrayArray, + op: VectorVectorToScalarOp +): Case[] { + return generateVectorVectorToScalarCases(param0s, param1s, op, quantizeToI64, abstractInt); +} diff --git a/src/webgpu/util/constants.ts b/src/webgpu/util/constants.ts index b7426114a497..11f067731646 100644 --- a/src/webgpu/util/constants.ts +++ b/src/webgpu/util/constants.ts @@ -252,6 +252,9 @@ export const kValue = { min: BigInt(-9223372036854775808n), max: BigInt(0n), }, + isOOB: (val: bigint): boolean => { + return val > kValue.i64.positive.max || val < kValue.i64.negative.min; + }, }, // Limits of i32 diff --git a/src/webgpu/util/math.ts b/src/webgpu/util/math.ts index 0883ba6ff2ee..090fcf0fe208 100644 --- a/src/webgpu/util/math.ts +++ b/src/webgpu/util/math.ts @@ -1354,6 +1354,41 @@ export function vectorI64Range(dim: number): ROArrayArray { return kVectorI64Values[dim]; } +const kSparseVectorI64Values = { + 2: sparseI64Range().map((i, idx) => [ + idx % 2 === 0 ? i : BigInt(idx), + idx % 2 === 1 ? i : -BigInt(idx), + ]), + 3: sparseI64Range().map((i, idx) => [ + idx % 3 === 0 ? i : BigInt(idx), + idx % 3 === 1 ? i : -BigInt(idx), + idx % 3 === 2 ? i : BigInt(idx), + ]), + 4: sparseI64Range().map((i, idx) => [ + idx % 4 === 0 ? i : BigInt(idx), + idx % 4 === 1 ? i : -BigInt(idx), + idx % 4 === 2 ? i : BigInt(idx), + idx % 4 === 3 ? i : -BigInt(idx), + ]), +}; + +/** + * Minimal set of vectors, indexed by dimension, that contain interesting + * abstract integer values. + * + * This is an even more stripped down version of `vectorI64Range` for when + * pairs of vectors are being tested. + * All interesting integers from sparseI64Range are guaranteed to be + * tested, but not in every position. + */ +export function sparseVectorI64Range(dim: number): ROArrayArray { + assert( + dim === 2 || dim === 3 || dim === 4, + 'sparseVectorI64Range only accepts dimensions 2, 3, and 4' + ); + return kSparseVectorI64Values[dim]; +} + /** * @returns an ascending sorted array of numbers spread over the entire range of 64-bit signed ints *