🏡 index : cold-air-networks/mirror-webgpu-cts.git

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};` : ''
  );
}

// Identity cases
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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// To i32 from u32, f32
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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// To u32 from i32, f32
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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// To f32 from i32, u32
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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// 16 bit types

// f16 cases

// f16: Identity
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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// f16: 32-bit scalar numeric to vec2<f16>
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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// f16: vec2<32-bit scalar numeric> to vec4<f16>
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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// f16: vec2<f16> to 32-bit scalar numeric
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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// f16: vec4<f16> to vec2<32-bit scalar numeric>
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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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(
      // Infinities and NaNs are errors in const-eval.
      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);
  });

// Abstract Float
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
    );
  });

// Abstract Int
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);
  });