From 92825c4c76db7f156d37b3478cbe09b6b533bf80 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Tue, 22 Feb 2022 23:01:20 +0000 Subject: [PATCH] wgsl: Add `extractBits` tests --- .../execution/builtin/extractBits.spec.ts | 341 ++++++++++++++++++ 1 file changed, 341 insertions(+) create mode 100644 src/webgpu/shader/execution/builtin/extractBits.spec.ts diff --git a/src/webgpu/shader/execution/builtin/extractBits.spec.ts b/src/webgpu/shader/execution/builtin/extractBits.spec.ts new file mode 100644 index 000000000000..007129be33d9 --- /dev/null +++ b/src/webgpu/shader/execution/builtin/extractBits.spec.ts @@ -0,0 +1,341 @@ +export const description = ` +Execution Tests for the 'extractBits' builtin function +`; + +import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../gpu_test.js'; +import { + i32Bits, + TypeI32, + u32, + TypeU32, + u32Bits, + vec2, + vec3, + vec4, + TypeVec, +} from '../../../util/conversion.js'; + +import { Config, run } from './builtin.js'; + +export const g = makeTestGroup(GPUTest); + +g.test('integer_builtin_functions,extractBits_unsigned') + .uniqueId('xxxxxxxxxxxxxxxx') + .specURL('https://www.w3.org/TR/2021/WD-WGSL-20210929/#integer-builtin-functions') + .desc( + ` +extractBits: +T is u32 or vecN extractBits(e: T, offset: u32, count: u32) -> T + +Reads bits from an integer, without sign extension. + +When T is a scalar type, then: + +* w is the bit width of T +* o = min(offset,w) +* c = min(count, w - o) +* The result is 0 if c is 0. +* Otherwise, bits 0..c-1 of the result are copied from bits o..o+c-1 of e. Other bits of the result are 0. + +Component-wise when T is a vector. + +Please read the following guidelines before contributing: +https://github.com/gpuweb/cts/blob/main/docs/plan_autogen.md +` + ) + .params(u => + u + .combine('storageClass', ['uniform', 'storage_r', 'storage_rw'] as const) + .combine('width', [1, 2, 3, 4]) + ) + .fn(async t => { + const cfg: Config = t.params; + + const T = t.params.width === 1 ? TypeU32 : TypeVec(t.params.width, TypeU32); + + const V = (x: number, y?: number, z?: number, w?: number) => { + y = y === undefined ? x : y; + z = z === undefined ? x : z; + w = w === undefined ? x : w; + + switch (t.params.width) { + case 1: + return u32Bits(x); + case 2: + return vec2(u32Bits(x), u32Bits(y)); + case 3: + return vec3(u32Bits(x), u32Bits(y), u32Bits(z)); + default: + return vec4(u32Bits(x), u32Bits(y), u32Bits(z), u32Bits(w)); + } + }; + + const all_1 = V(0b11111111111111111111111111111111); + const all_0 = V(0b00000000000000000000000000000000); + const low_1 = V(0b00000000000000000000000000000001); + const high_1 = V(0b10000000000000000000000000000000); + const pattern = V( + 0b00000000000111011100000000000000, + 0b11111111111000000011111111111111, + 0b00000000010101010101000000000000, + 0b00000000001010101010100000000000 + ); + + run(t, 'extractBits', [T, TypeU32, TypeU32], T, cfg, [ + { input: [all_0, u32(0), u32(32)], expected: all_0 }, + { input: [all_0, u32(1), u32(10)], expected: all_0 }, + { input: [all_0, u32(2), u32(5)], expected: all_0 }, + { input: [all_0, u32(0), u32(1)], expected: all_0 }, + { input: [all_0, u32(31), u32(1)], expected: all_0 }, + + { input: [all_1, u32(0), u32(32)], expected: all_1 }, + { + input: [all_1, u32(1), u32(10)], + expected: V(0b00000000000000000000001111111111), + }, + { + input: [all_1, u32(2), u32(5)], + expected: V(0b00000000000000000000000000011111), + }, + { input: [all_1, u32(0), u32(1)], expected: low_1 }, + { input: [all_1, u32(31), u32(1)], expected: low_1 }, + + // Patterns + { input: [pattern, u32(0), u32(32)], expected: pattern }, + { + input: [pattern, u32(1), u32(31)], + expected: V( + 0b00000000000011101110000000000000, + 0b01111111111100000001111111111111, + 0b00000000001010101010100000000000, + 0b00000000000101010101010000000000 + ), + }, + { + input: [pattern, u32(14), u32(18)], + expected: V( + 0b00000000000000000000000001110111, + 0b00000000000000111111111110000000, + 0b00000000000000000000000101010101, + 0b00000000000000000000000010101010 + ), + }, + { + input: [pattern, u32(14), u32(7)], + expected: V( + 0b00000000000000000000000001110111, + 0b00000000000000000000000000000000, + 0b00000000000000000000000001010101, + 0b00000000000000000000000000101010 + ), + }, + { + input: [pattern, u32(14), u32(4)], + expected: V( + 0b00000000000000000000000000000111, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000101, + 0b00000000000000000000000000001010 + ), + }, + { + input: [pattern, u32(14), u32(3)], + expected: V( + 0b00000000000000000000000000000111, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000101, + 0b00000000000000000000000000000010 + ), + }, + { + input: [pattern, u32(18), u32(3)], + expected: V( + 0b00000000000000000000000000000111, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000101, + 0b00000000000000000000000000000010 + ), + }, + { input: [low_1, u32(0), u32(1)], expected: low_1 }, + { input: [high_1, u32(31), u32(1)], expected: low_1 }, + + // End overflow + { input: [low_1, u32(0), u32(99)], expected: low_1 }, + { input: [high_1, u32(31), u32(99)], expected: low_1 }, + { input: [pattern, u32(0), u32(99)], expected: pattern }, + { + input: [pattern, u32(14), u32(99)], + expected: V( + 0b00000000000000000000000001110111, + 0b00000000000000111111111110000000, + 0b00000000000000000000000101010101, + 0b00000000000000000000000010101010 + ), + }, + + // Zero count + { input: [all_1, u32(0), u32(0)], expected: all_0 }, + { input: [all_0, u32(0), u32(0)], expected: all_0 }, + { input: [low_1, u32(0), u32(0)], expected: all_0 }, + { input: [high_1, u32(31), u32(0)], expected: all_0 }, + { input: [pattern, u32(0), u32(0)], expected: all_0 }, + ]); + }); + +g.test('integer_builtin_functions,extractBits_signed') + .uniqueId('xxxxxxxxxxxxxxxx') + .specURL('https://www.w3.org/TR/2021/WD-WGSL-20210929/#integer-builtin-functions') + .desc( + ` +extractBits: +T is i32 or vecN extractBits(e: T, offset: u32, count: u32) -> T + +Reads bits from an integer, with sign extension. + +When T is a scalar type, then: + +* w is the bit width of T +* o = min(offset,w) +* c = min(count, w - o) +* The result is 0 if c is 0. +* Otherwise, bits 0..c-1 of the result are copied from bits o..o+c-1 of e. Other bits of the result are the same as bit c-1 of the result. + +Component-wise when T is a vector. + +Please read the following guidelines before contributing: +https://github.com/gpuweb/cts/blob/main/docs/plan_autogen.md +` + ) + .params(u => + u + .combine('storageClass', ['uniform', 'storage_r', 'storage_rw'] as const) + .combine('width', [1, 2, 3, 4]) + ) + .fn(async t => { + const cfg: Config = t.params; + + const T = t.params.width === 1 ? TypeI32 : TypeVec(t.params.width, TypeI32); + + const V = (x: number, y?: number, z?: number, w?: number) => { + y = y === undefined ? x : y; + z = z === undefined ? x : z; + w = w === undefined ? x : w; + + switch (t.params.width) { + case 1: + return i32Bits(x); + case 2: + return vec2(i32Bits(x), i32Bits(y)); + case 3: + return vec3(i32Bits(x), i32Bits(y), i32Bits(z)); + default: + return vec4(i32Bits(x), i32Bits(y), i32Bits(z), i32Bits(w)); + } + }; + + const all_1 = V(0b11111111111111111111111111111111); + const all_0 = V(0b00000000000000000000000000000000); + const low_1 = V(0b00000000000000000000000000000001); + const high_1 = V(0b10000000000000000000000000000000); + const pattern = V( + 0b00000000000111011100000000000000, + 0b11111111111000000011111111111111, + 0b00000000010101010101000000000000, + 0b00000000001010101010100000000000 + ); + + run(t, 'extractBits', [T, TypeU32, TypeU32], T, cfg, [ + { input: [all_0, u32(0), u32(32)], expected: all_0 }, + { input: [all_0, u32(1), u32(10)], expected: all_0 }, + { input: [all_0, u32(2), u32(5)], expected: all_0 }, + { input: [all_0, u32(0), u32(1)], expected: all_0 }, + { input: [all_0, u32(31), u32(1)], expected: all_0 }, + + { input: [all_1, u32(0), u32(32)], expected: all_1 }, + { input: [all_1, u32(1), u32(10)], expected: all_1 }, + { input: [all_1, u32(2), u32(5)], expected: all_1 }, + { input: [all_1, u32(0), u32(1)], expected: all_1 }, + { input: [all_1, u32(31), u32(1)], expected: all_1 }, + + // Patterns + { input: [pattern, u32(0), u32(32)], expected: pattern }, + { + input: [pattern, u32(1), u32(31)], + expected: V( + 0b00000000000011101110000000000000, + 0b11111111111100000001111111111111, + 0b00000000001010101010100000000000, + 0b00000000000101010101010000000000 + ), + }, + { + input: [pattern, u32(14), u32(18)], + expected: V( + 0b00000000000000000000000001110111, + 0b11111111111111111111111110000000, + 0b00000000000000000000000101010101, + 0b00000000000000000000000010101010 + ), + }, + { + input: [pattern, u32(14), u32(7)], + expected: V( + 0b11111111111111111111111111110111, + 0b00000000000000000000000000000000, + 0b11111111111111111111111111010101, + 0b00000000000000000000000000101010 + ), + }, + { + input: [pattern, u32(14), u32(4)], + expected: V( + 0b00000000000000000000000000000111, + 0b00000000000000000000000000000000, + 0b00000000000000000000000000000101, + 0b11111111111111111111111111111010 + ), + }, + { + input: [pattern, u32(14), u32(3)], + expected: V( + 0b11111111111111111111111111111111, + 0b00000000000000000000000000000000, + 0b11111111111111111111111111111101, + 0b00000000000000000000000000000010 + ), + }, + { + input: [pattern, u32(18), u32(3)], + expected: V( + 0b11111111111111111111111111111111, + 0b00000000000000000000000000000000, + 0b11111111111111111111111111111101, + 0b00000000000000000000000000000010 + ), + }, + { input: [low_1, u32(0), u32(1)], expected: all_1 }, + { input: [high_1, u32(31), u32(1)], expected: all_1 }, + + // End overflow + { input: [low_1, u32(0), u32(99)], expected: low_1 }, + { input: [high_1, u32(31), u32(99)], expected: all_1 }, + { input: [pattern, u32(0), u32(99)], expected: pattern }, + { + input: [pattern, u32(14), u32(99)], + expected: V( + 0b00000000000000000000000001110111, + 0b11111111111111111111111110000000, + 0b00000000000000000000000101010101, + 0b00000000000000000000000010101010 + ), + }, + + // Zero count + { input: [all_1, u32(0), u32(0)], expected: all_0 }, + { input: [all_0, u32(0), u32(0)], expected: all_0 }, + { input: [low_1, u32(0), u32(0)], expected: all_0 }, + { input: [high_1, u32(31), u32(0)], expected: all_0 }, + { input: [pattern, u32(0), u32(0)], expected: all_0 }, + ]); + });