export const description = `
Execution tests for the 'bitcast' builtin function
@const @must_use fn bitcast<T>(e: T ) -> T
T is concrete numeric scalar or concerete numeric vector
Identity function.
@const @must_use fn bitcast<T>(e: S ) -> T
@const @must_use fn bitcast<vecN<T>>(e: vecN<S> ) -> vecN<T>
S is i32, u32, f32
T is i32, u32, f32, and T is not S
Reinterpretation of bits. Beware non-normal f32 values.
@const @must_use fn bitcast<u32>(e : Type.abstractInt) -> T
@const @must_use fn bitcast<vecN<u32>>(e : vecN<Type.abstractInt>) -> T
@const @must_use fn bitcast<T>(e: vec2<f16> ) -> T
@const @must_use fn bitcast<vec2<T>>(e: vec4<f16> ) -> vec2<T>
@const @must_use fn bitcast<vec2<f16>>(e: T ) -> vec2<f16>
@const @must_use fn bitcast<vec4<f16>>(e: vec2<T> ) -> vec4<f16>
T is i32, u32, f32
`;
import { TestParams } from '../../../../../../common/framework/fixture.js';
import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { AllFeaturesMaxLimitsGPUTest } from '../../../../../gpu_test.js';
import { anyOf } from '../../../../../util/compare.js';
import {
f32,
u32,
i32,
abstractFloat,
uint32ToFloat32,
u32Bits,
Type,
} from '../../../../../util/conversion.js';
import { FP } from '../../../../../util/floating_point.js';
import { scalarF32Range } from '../../../../../util/math.js';
import { ShaderBuilder, allInputSources, onlyConstInputSource, run } from '../../expression.js';
import { d } from './bitcast.cache.js';
import { builtinWithPredeclaration } from './builtin.js';
export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest);
* @returns a ShaderBuilder that generates a call to bitcast,
* using appropriate destination type, which optionally can be
* a WGSL type alias.
*/
function bitcastBuilder(canonicalDestType: string, params: TestParams): ShaderBuilder {
const destType = params.vectorize
? `vec${params.vectorize}<${canonicalDestType}>`
: canonicalDestType;
return builtinWithPredeclaration(
`bitcast<${destType}>`,
params.alias ? `alias myalias = ${destType};` : ''
);
}
g.test('i32_to_i32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast i32 to i32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get('i32_to_i32');
await run(t, bitcastBuilder('i32', t.params), [Type.i32], Type.i32, t.params, cases);
});
g.test('u32_to_u32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast u32 to u32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get('u32_to_u32');
await run(t, bitcastBuilder('u32', t.params), [Type.u32], Type.u32, t.params, cases);
});
g.test('f32_to_f32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast f32 to f32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get(
t.params.inputSource === 'const' ? 'f32_to_f32' : 'f32_inf_nan_to_f32'
);
await run(t, bitcastBuilder('f32', t.params), [Type.f32], Type.f32, t.params, cases);
});
g.test('u32_to_i32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast u32 to i32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get('u32_to_i32');
await run(t, bitcastBuilder('i32', t.params), [Type.u32], Type.i32, t.params, cases);
});
g.test('f32_to_i32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast f32 to i32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get(
t.params.inputSource === 'const' ? 'f32_to_i32' : 'f32_inf_nan_to_i32'
);
await run(t, bitcastBuilder('i32', t.params), [Type.f32], Type.i32, t.params, cases);
});
g.test('i32_to_u32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast i32 to u32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get('i32_to_u32');
await run(t, bitcastBuilder('u32', t.params), [Type.i32], Type.u32, t.params, cases);
});
g.test('f32_to_u32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast f32 to i32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get(
t.params.inputSource === 'const' ? 'f32_to_u32' : 'f32_inf_nan_to_u32'
);
await run(t, bitcastBuilder('u32', t.params), [Type.f32], Type.u32, t.params, cases);
});
g.test('i32_to_f32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast i32 to f32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get(
t.params.inputSource === 'const' ? 'i32_to_f32' : 'i32_to_f32_inf_nan'
);
await run(t, bitcastBuilder('f32', t.params), [Type.i32], Type.f32, t.params, cases);
});
g.test('u32_to_f32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast u32 to f32 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get(
t.params.inputSource === 'const' ? 'u32_to_f32' : 'u32_to_f32_inf_nan'
);
await run(t, bitcastBuilder('f32', t.params), [Type.u32], Type.f32, t.params, cases);
});
g.test('f16_to_f16')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast f16 to f16 tests`)
.params(u =>
u
.combine('inputSource', allInputSources)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'f16_to_f16' : 'f16_inf_nan_to_f16'
);
await run(t, bitcastBuilder('f16', t.params), [Type.f16], Type.f16, t.params, cases);
});
g.test('i32_to_vec2h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast i32 to vec2h tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'i32_to_vec2_f16' : 'i32_to_vec2_f16_inf_nan'
);
await run(t, bitcastBuilder('vec2<f16>', t.params), [Type.i32], Type.vec2h, t.params, cases);
});
g.test('u32_to_vec2h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast u32 to vec2h tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'u32_to_vec2_f16' : 'u32_to_vec2_f16_inf_nan'
);
await run(t, bitcastBuilder('vec2<f16>', t.params), [Type.u32], Type.vec2h, t.params, cases);
});
g.test('f32_to_vec2h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast u32 to vec2h tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'f32_to_vec2_f16' : 'f32_inf_nan_to_vec2_f16_inf_nan'
);
await run(t, bitcastBuilder('vec2<f16>', t.params), [Type.f32], Type.vec2h, t.params, cases);
});
g.test('vec2i_to_vec4h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec2i to vec4h tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'vec2_i32_to_vec4_f16' : 'vec2_i32_to_vec4_f16_inf_nan'
);
await run(t, bitcastBuilder('vec4<f16>', t.params), [Type.vec2i], Type.vec4h, t.params, cases);
});
g.test('vec2u_to_vec4h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec2u to vec4h tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'vec2_u32_to_vec4_f16' : 'vec2_u32_to_vec4_f16_inf_nan'
);
await run(t, bitcastBuilder('vec4<f16>', t.params), [Type.vec2u], Type.vec4h, t.params, cases);
});
g.test('vec2f_to_vec4h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec2f to vec2h tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const'
? 'vec2_f32_to_vec4_f16'
: 'vec2_f32_inf_nan_to_vec4_f16_inf_nan'
);
await run(t, bitcastBuilder('vec4<f16>', t.params), [Type.vec2f], Type.vec4h, t.params, cases);
});
g.test('vec2h_to_i32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec2h to i32 tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'vec2_f16_to_i32' : 'vec2_f16_inf_nan_to_i32'
);
await run(t, bitcastBuilder('i32', t.params), [Type.vec2h], Type.i32, t.params, cases);
});
g.test('vec2h_to_u32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec2h to u32 tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'vec2_f16_to_u32' : 'vec2_f16_inf_nan_to_u32'
);
await run(t, bitcastBuilder('u32', t.params), [Type.vec2h], Type.u32, t.params, cases);
});
g.test('vec2h_to_f32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec2h to f32 tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'vec2_f16_to_f32_finite' : 'vec2_f16_inf_nan_to_f32'
);
await run(t, bitcastBuilder('f32', t.params), [Type.vec2h], Type.f32, t.params, cases);
});
g.test('vec4h_to_vec2i')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec4h to vec2i tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'vec4_f16_to_vec2_i32' : 'vec4_f16_inf_nan_to_vec2_i32'
);
await run(t, bitcastBuilder('vec2<i32>', t.params), [Type.vec4h], Type.vec2i, t.params, cases);
});
g.test('vec4h_to_vec2u')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec4h to vec2u tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const' ? 'vec4_f16_to_vec2_u32' : 'vec4_f16_inf_nan_to_vec2_u32'
);
await run(t, bitcastBuilder('vec2<u32>', t.params), [Type.vec4h], Type.vec2u, t.params, cases);
});
g.test('vec4h_to_vec2f')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec4h to vec2f tests`)
.params(u => u.combine('inputSource', allInputSources).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get(
t.params.inputSource === 'const'
? 'vec4_f16_to_vec2_f32_finite'
: 'vec4_f16_inf_nan_to_vec2_f32'
);
await run(t, bitcastBuilder('vec2<f32>', t.params), [Type.vec4h], Type.vec2f, t.params, cases);
});
g.test('af_to_f32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract float to f32 tests`)
.params(u =>
u
.combine('inputSource', onlyConstInputSource)
.combine('vectorize', [undefined, 2, 3, 4] as const)
)
.fn(async t => {
const cases = scalarF32Range().map(u => {
const res = FP['f32'].addFlushedIfNeeded([u]).map(f => {
return f32(f);
});
return {
input: abstractFloat(u),
expected: anyOf(...res),
};
});
await run(t, bitcastBuilder('f32', t.params), [Type.abstractFloat], Type.f32, t.params, cases);
});
g.test('af_to_i32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract float to i32 tests`)
.params(u =>
u
.combine('inputSource', onlyConstInputSource)
.combine('vectorize', [undefined, 2, 3, 4] as const)
)
.fn(async t => {
const values = [
0,
1,
10,
256,
u32Bits(0b11111111011111111111111111111111).value,
u32Bits(0b11111111010000000000000000000000).value,
u32Bits(0b11111110110000000000000000000000).value,
u32Bits(0b11111101110000000000000000000000).value,
u32Bits(0b11111011110000000000000000000000).value,
u32Bits(0b11110111110000000000000000000000).value,
u32Bits(0b11101111110000000000000000000000).value,
u32Bits(0b11011111110000000000000000000000).value,
u32Bits(0b10111111110000000000000000000000).value,
u32Bits(0b01111111011111111111111111111111).value,
u32Bits(0b01111111010000000000000000000000).value,
u32Bits(0b01111110110000000000000000000000).value,
u32Bits(0b01111101110000000000000000000000).value,
u32Bits(0b01111011110000000000000000000000).value,
u32Bits(0b01110111110000000000000000000000).value,
u32Bits(0b01101111110000000000000000000000).value,
u32Bits(0b01011111110000000000000000000000).value,
u32Bits(0b00111111110000000000000000000000).value,
];
const cases = values.map(u => {
return {
input: abstractFloat(uint32ToFloat32(u)),
expected: i32(u),
};
});
await run(t, bitcastBuilder('i32', t.params), [Type.abstractFloat], Type.i32, t.params, cases);
});
g.test('af_to_u32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract float to u32 tests`)
.params(u =>
u
.combine('inputSource', onlyConstInputSource)
.combine('vectorize', [undefined, 2, 3, 4] as const)
)
.fn(async t => {
const values = [
0,
1,
10,
256,
u32Bits(0b11111111011111111111111111111111).value,
u32Bits(0b11111111010000000000000000000000).value,
u32Bits(0b11111110110000000000000000000000).value,
u32Bits(0b11111101110000000000000000000000).value,
u32Bits(0b11111011110000000000000000000000).value,
u32Bits(0b11110111110000000000000000000000).value,
u32Bits(0b11101111110000000000000000000000).value,
u32Bits(0b11011111110000000000000000000000).value,
u32Bits(0b10111111110000000000000000000000).value,
u32Bits(0b01111111011111111111111111111111).value,
u32Bits(0b01111111010000000000000000000000).value,
u32Bits(0b01111110110000000000000000000000).value,
u32Bits(0b01111101110000000000000000000000).value,
u32Bits(0b01111011110000000000000000000000).value,
u32Bits(0b01110111110000000000000000000000).value,
u32Bits(0b01101111110000000000000000000000).value,
u32Bits(0b01011111110000000000000000000000).value,
u32Bits(0b00111111110000000000000000000000).value,
];
const cases = values.map(u => {
return {
input: abstractFloat(uint32ToFloat32(u)),
expected: u32(u),
};
});
await run(t, bitcastBuilder('u32', t.params), [Type.abstractFloat], Type.u32, t.params, cases);
});
g.test('af_to_vec2f16')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract float to f16 tests`)
.params(u => u.combine('inputSource', onlyConstInputSource))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get('af_to_vec2_f16');
await run(
t,
bitcastBuilder('vec2<f16>', t.params),
[Type.abstractFloat],
Type.vec2h,
t.params,
cases
);
});
g.test('vec2af_to_vec4f16')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract float to f16 tests`)
.params(u => u.combine('inputSource', onlyConstInputSource))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get('vec2_af_to_vec4_f16');
await run(
t,
bitcastBuilder('vec4<f16>', t.params),
[Type.vec(2, Type.abstractFloat)],
Type.vec4h,
t.params,
cases
);
});
g.test('ai_to_i32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract int to i32 tests`)
.params(u =>
u
.combine('inputSource', onlyConstInputSource)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get('ai_to_i32');
await run(t, bitcastBuilder('i32', t.params), [Type.abstractInt], Type.i32, t.params, cases);
});
g.test('ai_to_u32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract int to u32 tests`)
.params(u =>
u
.combine('inputSource', onlyConstInputSource)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get('ai_to_u32');
await run(t, bitcastBuilder('u32', t.params), [Type.abstractInt], Type.u32, t.params, cases);
});
g.test('ai_to_f32')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast abstract int to f32 tests`)
.params(u =>
u
.combine('inputSource', onlyConstInputSource)
.combine('vectorize', [undefined, 2, 3, 4] as const)
.combine('alias', [false, true])
)
.fn(async t => {
const cases = await d.get('ai_to_f32');
await run(t, bitcastBuilder('f32', t.params), [Type.abstractInt], Type.f32, t.params, cases);
});
g.test('ai_to_vec2h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast ai to vec2h tests`)
.params(u => u.combine('inputSource', onlyConstInputSource).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get('ai_to_vec2_f16');
await run(
t,
bitcastBuilder('vec2<f16>', t.params),
[Type.abstractInt],
Type.vec2h,
t.params,
cases
);
});
g.test('vec2ai_to_vec4h')
.specURL('https://www.w3.org/TR/WGSL/#bitcast-builtin')
.desc(`bitcast vec2ai to vec4h tests`)
.params(u => u.combine('inputSource', onlyConstInputSource).combine('alias', [false, true]))
.fn(async t => {
t.skipIfDeviceDoesNotHaveFeature('shader-f16');
const cases = await d.get('vec2_ai_to_vec4_f16');
await run(t, bitcastBuilder('vec4<f16>', t.params), [Type.vec2ai], Type.vec4h, t.params, cases);
});