Skip to content

Commit

Permalink
wgsl: Add AbstractFloat mix execution tests
Browse files Browse the repository at this point in the history
Fixes #2566
  • Loading branch information
zoddicus committed Oct 24, 2023
1 parent d491499 commit de68a79
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 29 deletions.
51 changes: 46 additions & 5 deletions src/unittests/floating_point.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5342,10 +5342,9 @@ const kMixImpreciseIntervalCases = {
{ input: [-1.0, 1.0, 0.9], expected: [reinterpretU64AsF64(0x3fe9_9999_8000_0000n), reinterpretU64AsF64(0x3fe9_9999_c000_0000n)] }, // ~0.8

// Showing how precise and imprecise versions diff
// Note that this expectation is 0 only in f32 as 10.0 is much smaller that f32.negative.min,
// Note that this expectation is 0 in f32 as 10.0 is much smaller that f32.negative.min,
// So that 10 - f32.negative.min == f32.negative.min even in f64. But for f16, there is not
// a exactly-represenatble f16 value v that make v - f16.negative.min == f16.negative.min
// in f64, in fact that require v being smaller than 2**-37.
// an exactly-represenatble f16 value v that make v - f16.negative.min == f16.negative.min
{ input: [kValue.f32.negative.min, 10.0, 1.0], expected: 0.0 },
// -10.0 is the same, much smaller than f32.negative.min
{ input: [kValue.f32.negative.min, -10.0, 1.0], expected: 0.0 },
Expand Down Expand Up @@ -5375,12 +5374,37 @@ const kMixImpreciseIntervalCases = {
// The result is -65504 + 65472 = -32 or -65504 + 65504 = 0.
{ input: [kValue.f16.negative.min, -10.0, 1.0], expected: [-32, 0] },
] as ScalarTripleToIntervalCase[],
abstract: [
// [0.0, 1.0] cases
{ input: [0.0, 1.0, 0.1], expected: 0.1 },
{ input: [0.0, 1.0, 0.9], expected: 0.9 },
// [1.0, 0.0] cases
{ input: [1.0, 0.0, 0.1], expected: 0.9 },
{ input: [1.0, 0.0, 0.9], expected: kMinusNULPFunctions['abstract'](0.1, 2) }, // This not being 0.1 is related to https://github.com/gpuweb/cts/issues/2993
// [0.0, 10.0] cases
{ input: [0.0, 10.0, 0.1], expected: 1 },
{ input: [0.0, 10.0, 0.9], expected: 9 },
// [2.0, 10.0] cases
{ input: [2.0, 10.0, 0.1], expected: 2.8 },
{ input: [2.0, 10.0, 0.9], expected: 9.2 },
// [-1.0, 1.0] cases
{ input: [-1.0, 1.0, 0.1], expected: -0.8 },
{ input: [-1.0, 1.0, 0.9], expected: 0.8 },

// Showing how precise and imprecise versions diff
// Note that this expectation is 0 in f64 as 10.0 is much smaller that f63.negative.min,
// So that 10 - f64.negative.min == f64.negative.min even in f64. But for f16, there is not
// an exactly-represenatble f16 value v that make v - f16.negative.min == f16.negative.min
{ input: [kValue.f64.negative.min, 10.0, 1.0], expected: 0.0 },
// -10.0 is the same, much smaller than f64.negative.min
{ input: [kValue.f64.negative.min, -10.0, 1.0], expected: 0.0 },
] as ScalarTripleToIntervalCase[],
} as const;

g.test('mixImpreciseInterval')
.params(u =>
u
.combine('trait', ['f32', 'f16'] as const)
.combine('trait', ['f32', 'f16', 'abstract'] as const)
.beginSubcases()
.expandWithParams<ScalarTripleToIntervalCase>(p => {
const trait = FP[p.trait];
Expand Down Expand Up @@ -5490,12 +5514,29 @@ const kMixPreciseIntervalCases = {
{ input: [-1.0, 1.0, 0.1], expected: [reinterpretU64AsF64(0xbfe9_a000_0000_0000n), reinterpretU64AsF64(0xbfe9_9800_0000_0000n)] }, // ~-0.8
{ input: [-1.0, 1.0, 0.9], expected: [reinterpretU64AsF64(0x3fe9_9800_0000_0000n), reinterpretU64AsF64(0x3fe9_a000_0000_0000n)] }, // ~0.8
] as ScalarTripleToIntervalCase[],
abstract: [
// [0.0, 1.0] cases
{ input: [0.0, 1.0, 0.1], expected: 0.1 },
{ input: [0.0, 1.0, 0.9], expected: 0.9 },
// [1.0, 0.0] cases
{ input: [1.0, 0.0, 0.1], expected: 0.9 },
{ input: [1.0, 0.0, 0.9], expected: kMinusNULPFunctions['abstract'](0.1, 2) }, // This not being 0.1 is related to https://github.com/gpuweb/cts/issues/2993
// [0.0, 10.0] cases
{ input: [0.0, 10.0, 0.1], expected: 1 },
{ input: [0.0, 10.0, 0.9], expected: 9 },
// [2.0, 10.0] cases
{ input: [2.0, 10.0, 0.1], expected: 2.8 },
{ input: [2.0, 10.0, 0.9], expected: 9.2 },
// [-1.0, 1.0] cases
{ input: [-1.0, 1.0, 0.1], expected: -0.8 },
{ input: [-1.0, 1.0, 0.9], expected: 0.8 },
] as ScalarTripleToIntervalCase[],
} as const;

g.test('mixPreciseInterval')
.params(u =>
u
.combine('trait', ['f32', 'f16'] as const)
.combine('trait', ['f32', 'f16', 'abstract'] as const)
.beginSubcases()
.expandWithParams<ScalarTripleToIntervalCase>(p => {
const trait = FP[p.trait];
Expand Down
8 changes: 4 additions & 4 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1277,10 +1277,10 @@
"webgpu:shader,execution,expression,call,builtin,min:f32:*": { "subcaseMS": 298.463 },
"webgpu:shader,execution,expression,call,builtin,min:i32:*": { "subcaseMS": 7.825 },
"webgpu:shader,execution,expression,call,builtin,min:u32:*": { "subcaseMS": 6.932 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_matching:*": { "subcaseMS": 215.206 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_nonmatching_vec2:*": { "subcaseMS": 14.601 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_nonmatching_vec3:*": { "subcaseMS": 18.302 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_nonmatching_vec4:*": { "subcaseMS": 12.602 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_matching:*": { "subcaseMS": 30026.025 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_nonmatching_vec2:*": { "subcaseMS": 16161.901 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_nonmatching_vec3:*": { "subcaseMS": 25039.601 },
"webgpu:shader,execution,expression,call,builtin,mix:abstract_float_nonmatching_vec4:*": { "subcaseMS": 11499.101 },
"webgpu:shader,execution,expression,call,builtin,mix:f16_matching:*": { "subcaseMS": 321.700 },
"webgpu:shader,execution,expression,call,builtin,mix:f16_nonmatching_vec2:*": { "subcaseMS": 653.851 },
"webgpu:shader,execution,expression,call,builtin,mix:f16_nonmatching_vec3:*": { "subcaseMS": 832.076 },
Expand Down
92 changes: 80 additions & 12 deletions src/webgpu/shader/execution/expression/call/builtin/mix.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ Same as mix(e1,e2,T2(e3)).

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { GPUTest } from '../../../../../gpu_test.js';
import { TypeVec, TypeF32, TypeF16 } from '../../../../../util/conversion.js';
import { TypeVec, TypeF32, TypeF16, TypeAbstractFloat } from '../../../../../util/conversion.js';
import { FP } from '../../../../../util/floating_point.js';
import {
sparseF32Range,
sparseF16Range,
sparseVectorF32Range,
sparseVectorF16Range,
sparseVectorF64Range,
sparseF64Range,
} from '../../../../../util/math.js';
import { makeCaseCache } from '../../case_cache.js';
import { allInputSources, run } from '../../expression.js';
import { allInputSources, onlyConstInputSource, run } from '../../expression.js';

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

export const g = makeTestGroup(GPUTest);

Expand Down Expand Up @@ -65,6 +67,21 @@ const f16_vec_scalar_cases = ([2, 3, 4] as const)
)
.reduce((a, b) => ({ ...a, ...b }), {});

// Cases: abstract_vecN_scalar
const abstract_vec_scalar_cases = ([2, 3, 4] as const)
.map(n => ({
[`abstract_vec${n}_scalar`]: () => {
return FP.abstract.generateVectorPairScalarToVectorComponentWiseCase(
sparseVectorF64Range(n),
sparseVectorF64Range(n),
sparseF64Range(),
'finite',
...FP.abstract.mixIntervals
);
},
}))
.reduce((a, b) => ({ ...a, ...b }), {});

export const d = makeCaseCache('mix', {
f32_const: () => {
return FP.f32.generateScalarTripleToIntervalCases(
Expand Down Expand Up @@ -104,33 +121,84 @@ export const d = makeCaseCache('mix', {
);
},
...f16_vec_scalar_cases,
abstract: () => {
return FP.abstract.generateScalarTripleToIntervalCases(
sparseF64Range(),
sparseF64Range(),
sparseF64Range(),
'finite',
...FP.abstract.mixIntervals
);
},
...abstract_vec_scalar_cases,
});

g.test('abstract_float_matching')
.specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
.desc(`abstract_float test with matching third param`)
.params(u =>
u.combine('inputSource', allInputSources).combine('vectorize', [undefined, 2, 3, 4] as const)
u
.combine('inputSource', onlyConstInputSource)
.combine('vectorize', [undefined, 2, 3, 4] as const)
)
.unimplemented();

.fn(async t => {
const cases = await d.get('abstract');
await run(
t,
abstractBuiltin('mix'),
[TypeAbstractFloat, TypeAbstractFloat, TypeAbstractFloat],
TypeAbstractFloat,
t.params,
cases
);
});
g.test('abstract_float_nonmatching_vec2')
.specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
.desc(`abstract_float tests with two vec2<abstract_float> params and scalar third param`)
.params(u => u.combine('inputSource', allInputSources))
.unimplemented();
.params(u => u.combine('inputSource', onlyConstInputSource))
.fn(async t => {
const cases = await d.get('abstract_vec2_scalar');
await run(
t,
abstractBuiltin('mix'),
[TypeVec(2, TypeAbstractFloat), TypeVec(2, TypeAbstractFloat), TypeAbstractFloat],
TypeVec(2, TypeAbstractFloat),
t.params,
cases
);
});

g.test('abstract_float_nonmatching_vec3')
.specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
.desc(`abstract_float tests with two vec3<abstract_float> params and scalar third param`)
.params(u => u.combine('inputSource', allInputSources))
.unimplemented();
.params(u => u.combine('inputSource', onlyConstInputSource))
.fn(async t => {
const cases = await d.get('abstract_vec3_scalar');
await run(
t,
abstractBuiltin('mix'),
[TypeVec(3, TypeAbstractFloat), TypeVec(3, TypeAbstractFloat), TypeAbstractFloat],
TypeVec(3, TypeAbstractFloat),
t.params,
cases
);
});

g.test('abstract_float_nonmatching_vec4')
.specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
.desc(`abstract_float tests with two vec4<abstract_float> params and scalar third param`)
.params(u => u.combine('inputSource', allInputSources))
.unimplemented();
.params(u => u.combine('inputSource', onlyConstInputSource))
.fn(async t => {
const cases = await d.get('abstract_vec3_scalar');
await run(
t,
abstractBuiltin('mix'),
[TypeVec(3, TypeAbstractFloat), TypeVec(3, TypeAbstractFloat), TypeAbstractFloat],
TypeVec(3, TypeAbstractFloat),
t.params,
cases
);
});

g.test('f32_matching')
.specURL('https://www.w3.org/TR/WGSL/#float-builtin-functions')
Expand Down
10 changes: 2 additions & 8 deletions src/webgpu/util/floating_point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5018,14 +5018,8 @@ class FPAbstractTraits extends FPTraits {
public readonly log2Interval = this.unimplementedScalarToInterval.bind(this, 'log2Interval');
public readonly maxInterval = this.maxIntervalImpl.bind(this);
public readonly minInterval = this.minIntervalImpl.bind(this);
public readonly mixImpreciseInterval = this.unimplementedScalarTripleToInterval.bind(
this,
'mixImpreciseInterval'
);
public readonly mixPreciseInterval = this.unimplementedScalarTripleToInterval.bind(
this,
'mixPreciseInterval'
);
public readonly mixImpreciseInterval = this.mixImpreciseIntervalImpl.bind(this);
public readonly mixPreciseInterval = this.mixPreciseIntervalImpl.bind(this);
public readonly mixIntervals = [this.mixImpreciseInterval, this.mixPreciseInterval];
public readonly modfInterval = this.modfIntervalImpl.bind(this);
public readonly multiplicationInterval = this.multiplicationIntervalImpl.bind(this);
Expand Down

0 comments on commit de68a79

Please sign in to comment.