Skip to content

Commit

Permalink
wgsl: Add AbstractInt select execution tests (#3378)
Browse files Browse the repository at this point in the history
Fixes #3173
  • Loading branch information
zoddicus authored Feb 8, 2024
1 parent d759c05 commit c0742d6
Showing 1 changed file with 53 additions and 32 deletions.
85 changes: 53 additions & 32 deletions src/webgpu/shader/execution/expression/call/builtin/select.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,44 +32,62 @@ import {
vec4,
abstractFloat,
TypeAbstractFloat,
TypeAbstractInt,
abstractInt,
Scalar,
} from '../../../../../util/conversion.js';
import { CaseList } from '../../case.js';
import { run, allInputSources } from '../../expression.js';

import { abstractFloatBuiltin, builtin } from './builtin.js';
import { abstractFloatBuiltin, abstractIntBuiltin, builtin } from './builtin.js';

export const g = makeTestGroup(GPUTest);

function makeBool(n: number) {
return bool((n & 1) === 1);
}

type scalarKind = 'b' | 'af' | 'f' | 'h' | 'i' | 'u';
type scalarKind = 'b' | 'af' | 'f' | 'h' | 'ai' | 'i' | 'u';

const dataType = {
b: {
type: TypeBool,
constructor: makeBool,
scalar_builder: makeBool,
shader_builder: builtin('select'),
},
af: {
type: TypeAbstractFloat,
constructor: abstractFloat,
scalar_builder: abstractFloat,
shader_builder: abstractFloatBuiltin('select'),
},
f: {
type: TypeF32,
constructor: f32,
scalar_builder: f32,
shader_builder: builtin('select'),
},
h: {
type: TypeF16,
constructor: f16,
scalar_builder: f16,
shader_builder: builtin('select'),
},
ai: {
type: TypeAbstractInt,
// Only ints are used in the tests below, so the conversion to bigint will
// be safe. If a non-int is passed in this will Error.
scalar_builder: (v: number): Scalar => {
return abstractInt(BigInt(v));
},
shader_builder: abstractIntBuiltin('select'),
},
i: {
type: TypeI32,
constructor: i32,
scalar_builder: i32,
shader_builder: builtin('select'),
},
u: {
type: TypeU32,
constructor: u32,
scalar_builder: u32,
shader_builder: builtin('select'),
},
};

Expand All @@ -79,40 +97,42 @@ g.test('scalar')
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('component', ['b', 'af', 'f', 'h', 'i', 'u'] as const)
.combine('component', ['b', 'af', 'f', 'h', 'ai', 'i', 'u'] as const)
.combine('overload', ['scalar', 'vec2', 'vec3', 'vec4'] as const)
)
.beforeAllSubcases(t => {
if (t.params.component === 'h') {
t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] });
}
t.skipIf(t.params.component === 'af' && t.params.inputSource !== 'const');
t.skipIf(t.params.component === 'ai' && t.params.inputSource !== 'const');
})
.fn(async t => {
const componentType = dataType[t.params.component as scalarKind].type;
const cons = dataType[t.params.component as scalarKind].constructor;
const componentType = dataType[t.params.component].type;
const scalar_builder = dataType[t.params.component].scalar_builder;

// Create the scalar values that will be selected from, either as scalars
// or vectors.
//
// Each boolean will select between c[k] and c[k+4]. Those values must
// always compare as different. The tricky case is boolean, where the parity
// has to be different, i.e. c[k]-c[k+4] must be odd.
const c = [0, 1, 2, 3, 5, 6, 7, 8].map(i => cons(i));
const scalars = [0, 1, 2, 3, 5, 6, 7, 8].map(i => scalar_builder(i));

// Now form vectors that will have different components from each other.
const v2a = vec2(c[0], c[1]);
const v2b = vec2(c[4], c[5]);
const v3a = vec3(c[0], c[1], c[2]);
const v3b = vec3(c[4], c[5], c[6]);
const v4a = vec4(c[0], c[1], c[2], c[3]);
const v4b = vec4(c[4], c[5], c[6], c[7]);
const v2a = vec2(scalars[0], scalars[1]);
const v2b = vec2(scalars[4], scalars[5]);
const v3a = vec3(scalars[0], scalars[1], scalars[2]);
const v3b = vec3(scalars[4], scalars[5], scalars[6]);
const v4a = vec4(scalars[0], scalars[1], scalars[2], scalars[3]);
const v4b = vec4(scalars[4], scalars[5], scalars[6], scalars[7]);

const overloads = {
scalar: {
type: componentType,
cases: [
{ input: [c[0], c[1], False], expected: c[0] },
{ input: [c[0], c[1], True], expected: c[1] },
{ input: [scalars[0], scalars[1], False], expected: scalars[0] },
{ input: [scalars[0], scalars[1], True], expected: scalars[1] },
],
},
vec2: {
Expand Down Expand Up @@ -141,7 +161,7 @@ g.test('scalar')

await run(
t,
t.params.component === 'af' ? abstractFloatBuiltin('select') : builtin('select'),
dataType[t.params.component as scalarKind].shader_builder,
[overload.type, overload.type, TypeBool],
overload.type,
t.params,
Expand All @@ -155,34 +175,35 @@ g.test('vector')
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('component', ['b', 'af', 'f', 'h', 'i', 'u'] as const)
.combine('component', ['b', 'af', 'f', 'h', 'ai', 'i', 'u'] as const)
.combine('overload', ['vec2', 'vec3', 'vec4'] as const)
)
.beforeAllSubcases(t => {
if (t.params.component === 'h') {
t.selectDeviceOrSkipTestCase({ requiredFeatures: ['shader-f16'] });
}
t.skipIf(t.params.component === 'af' && t.params.inputSource !== 'const');
t.skipIf(t.params.component === 'ai' && t.params.inputSource !== 'const');
})
.fn(async t => {
const componentType = dataType[t.params.component as scalarKind].type;
const cons = dataType[t.params.component as scalarKind].constructor;
const componentType = dataType[t.params.component].type;
const scalar_builder = dataType[t.params.component].scalar_builder;

// Create the scalar values that will be selected from.
//
// Each boolean will select between c[k] and c[k+4]. Those values must
// always compare as different. The tricky case is boolean, where the parity
// has to be different, i.e. c[k]-c[k+4] must be odd.
const c = [0, 1, 2, 3, 5, 6, 7, 8].map(i => cons(i));
const scalars = [0, 1, 2, 3, 5, 6, 7, 8].map(i => scalar_builder(i));
const T = True;
const F = False;

let tests: { dataType: VectorType; boolType: VectorType; cases: CaseList };

switch (t.params.overload) {
case 'vec2': {
const a = vec2(c[0], c[1]);
const b = vec2(c[4], c[5]);
const a = vec2(scalars[0], scalars[1]);
const b = vec2(scalars[4], scalars[5]);
tests = {
dataType: TypeVec(2, componentType),
boolType: TypeVec(2, TypeBool),
Expand All @@ -196,8 +217,8 @@ g.test('vector')
break;
}
case 'vec3': {
const a = vec3(c[0], c[1], c[2]);
const b = vec3(c[4], c[5], c[6]);
const a = vec3(scalars[0], scalars[1], scalars[2]);
const b = vec3(scalars[4], scalars[5], scalars[6]);
tests = {
dataType: TypeVec(3, componentType),
boolType: TypeVec(3, TypeBool),
Expand All @@ -215,8 +236,8 @@ g.test('vector')
break;
}
case 'vec4': {
const a = vec4(c[0], c[1], c[2], c[3]);
const b = vec4(c[4], c[5], c[6], c[7]);
const a = vec4(scalars[0], scalars[1], scalars[2], scalars[3]);
const b = vec4(scalars[4], scalars[5], scalars[6], scalars[7]);
tests = {
dataType: TypeVec(4, componentType),
boolType: TypeVec(4, TypeBool),
Expand Down Expand Up @@ -245,7 +266,7 @@ g.test('vector')

await run(
t,
t.params.component === 'af' ? abstractFloatBuiltin('select') : builtin('select'),
dataType[t.params.component].shader_builder,
[tests.dataType, tests.dataType, tests.boolType],
tests.dataType,
t.params,
Expand Down

0 comments on commit c0742d6

Please sign in to comment.