Skip to content

Commit

Permalink
wgsl: Add dot4I8Packed and dot4U8Packed execution tests (#3293)
Browse files Browse the repository at this point in the history
* wgsl: Add `dot4I8Packed` and `dot4U8Packed` execution tests

* Compute the expected values
  • Loading branch information
Jiawei-Shao authored Jan 22, 2024
1 parent cb56e17 commit 7528d64
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,8 @@
"webgpu:shader,execution,expression,call,builtin,dot:f32_vec4:*": { "subcaseMS": 11.876 },
"webgpu:shader,execution,expression,call,builtin,dot:i32:*": { "subcaseMS": 3.103 },
"webgpu:shader,execution,expression,call,builtin,dot:u32:*": { "subcaseMS": 3.101 },
"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,dpdx:f32:*": { "subcaseMS": 22.804 },
"webgpu:shader,execution,expression,call,builtin,dpdxCoarse:f32:*": { "subcaseMS": 22.404 },
"webgpu:shader,execution,expression,call,builtin,dpdxFine:f32:*": { "subcaseMS": 17.708 },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
export const description = `
Execution tests for the 'dot4I8Packed' builtin function
@const fn dot4I8Packed(e1: u32 ,e2: u32) -> i32
e1 and e2 are interpreted as vectors with four 8-bit signed integer components. Return the signed
integer dot product of these two vectors. Each component is sign-extended to i32 before performing
the multiply, and then the add operations are done in WGSL i32 with wrapping behaviour.
`;

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { GPUTest } from '../../../../../gpu_test.js';
import { TypeI32, TypeU32, i32, u32 } from '../../../../../util/conversion.js';
import { Case } from '../../case.js';
import { allInputSources, Config, run } from '../../expression.js';

import { builtin } from './builtin.js';

export const g = makeTestGroup(GPUTest);

g.test('basic')
.specURL('https://www.w3.org/TR/WGSL/#dot4I8Packed-builtin')
.desc(
`
@const fn dot4I8Packed(e1: u32, e2: u32) -> i32
`
)
.params(u => u.combine('inputSource', allInputSources))
.fn(async t => {
const cfg: Config = t.params;

const dot4I8Packed = (e1: number, e2: number) => {
let result = 0;
for (let i = 0; i < 4; ++i) {
let e1_i = (e1 >> (i * 8)) & 0xff;
if (e1_i >= 128) {
e1_i -= 256;
}
let e2_i = (e2 >> (i * 8)) & 0xff;
if (e2_i >= 128) {
e2_i -= 256;
}
result += e1_i * e2_i;
}
return result;
};

const testInputs = [
// dot({0, 0, 0, 0}, {0, 0, 0, 0})
[0, 0],
// dot({127, 127, 127, 127}, {127, 127, 127, 127})
[0x7f7f7f7f, 0x7f7f7f7f],
// dot({-128, -128, -128, -128}, {-128, -128, -128, -128})
[0x80808080, 0x80808080],
// dot({127, 127, 127, 127}, {-128, -128, -128, -128})
[0x7f7f7f7f, 0x80808080],
// dot({1, 2, 3, 4}, {5, 6, 7, 8})
[0x01020304, 0x05060708],
// dot({1, 2, 3, 4}, {-1, -2, -3, -4})
[0x01020304, 0xfffefdfc],
// dot({-5, -6, -7, -8}, {5, 6, 7, 8})
[0xfbfaf9f8, 0x05060708],
// dot({-9, -10, -11, -12}, {-13, -14, -15, -16})
[0xf7f6f5f4, 0xf3f2f1f0],
] as const;

const makeCase = (x: number, y: number): Case => {
return { input: [u32(x), u32(y)], expected: i32(dot4I8Packed(x, y)) };
};
const cases: Array<Case> = testInputs.flatMap(v => {
return [makeCase(...(v as [number, number]))];
});

await run(t, builtin('dot4I8Packed'), [TypeU32, TypeU32], TypeI32, cfg, cases);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export const description = `
Execution tests for the 'dot4U8Packed' builtin function
@const fn dot4U8Packed(e1: u32 ,e2: u32) -> u32
e1 and e2 are interpreted as vectors with four 8-bit unsigned integer components. Return the
unsigned integer dot product of these two vectors.
`;

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { GPUTest } from '../../../../../gpu_test.js';
import { TypeU32, u32 } from '../../../../../util/conversion.js';
import { Case } from '../../case.js';
import { allInputSources, Config, run } from '../../expression.js';

import { builtin } from './builtin.js';

export const g = makeTestGroup(GPUTest);

g.test('basic')
.specURL('https://www.w3.org/TR/WGSL/#dot4U8Packed-builtin')
.desc(
`
@const fn dot4U8Packed(e1: u32, e2: u32) -> u32
`
)
.params(u => u.combine('inputSource', allInputSources))
.fn(async t => {
const cfg: Config = t.params;

const dot4U8Packed = (e1: number, e2: number) => {
let result = 0;
for (let i = 0; i < 4; ++i) {
const e1_i = (e1 >> (i * 8)) & 0xff;
const e2_i = (e2 >> (i * 8)) & 0xff;
result += e1_i * e2_i;
}
return result;
};

const testInputs = [
// dot({0, 0, 0, 0}, {0, 0, 0, 0})
[0, 0],
// dot({255u, 255u, 255u, 255u}, {255u, 255u, 255u, 255u})
[0xffffffff, 0xffffffff],
// dot({1u, 2u, 3u, 4u}, {5u, 6u, 7u, 8u})
[0x01020304, 0x05060708],
// dot({120u, 90u, 60u, 30u}, {50u, 100u, 150u, 200u})
[0x785a3c1e, 0x326496c8],
] as const;

const makeCase = (x: number, y: number): Case => {
return { input: [u32(x), u32(y)], expected: u32(dot4U8Packed(x, y)) };
};
const cases: Array<Case> = testInputs.flatMap(v => {
return [makeCase(...(v as [number, number]))];
});

await run(t, builtin('dot4U8Packed'), [TypeU32, TypeU32], TypeU32, cfg, cases);
});

0 comments on commit 7528d64

Please sign in to comment.