Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
49f8a4d
commit 92825c4
Showing
1 changed file
with
341 additions
and
0 deletions.
There are no files selected for viewing
341 changes: 341 additions & 0 deletions
341
src/webgpu/shader/execution/builtin/extractBits.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<u32> 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<i32> 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 }, | ||
]); | ||
}); |