export const description = `Test that variables in the shader are value initialized`;import { makeTestGroup } from '../../../common/framework/test_group.js';import { AllFeaturesMaxLimitsGPUTest, GPUTest } from '../../gpu_test.js';import { Type } from '../../util/conversion.js';export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest);function generateShader(isF16: boolean,addressSpace: string,typeDecl: string,testValue: string,comparison: string): string {let moduleScope = `${isF16 ? 'enable f16;' : ''}struct Output {failed : atomic<u32>}@group(0) @binding(0) var<storage, read_write> output : Output;`;let functionScope = '';switch (addressSpace) {case 'private':moduleScope += `\nvar<private> testVar: ${typeDecl} = ${testValue};`;break;case 'function':functionScope += `\nvar testVar: ${typeDecl} = ${testValue};`;break;}return `${moduleScope}@compute @workgroup_size(1, 1, 1)fn main() {${functionScope}${comparison}}`;}async function run(t: GPUTest, wgsl: string) {const pipeline = await t.device.createComputePipelineAsync({layout: 'auto',compute: {module: t.device.createShaderModule({code: wgsl,}),entryPoint: 'main',},});const resultBuffer = t.createBufferTracked({size: 4,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,});const bindGroup = t.device.createBindGroup({layout: pipeline.getBindGroupLayout(0),entries: [{binding: 0,resource: {buffer: resultBuffer,},},],});const encoder = t.device.createCommandEncoder();const pass = encoder.beginComputePass();pass.setPipeline(pipeline);pass.setBindGroup(0, bindGroup);pass.dispatchWorkgroups(1);pass.end();t.queue.submit([encoder.finish()]);t.expectGPUBufferValuesEqual(resultBuffer, new Uint32Array([0]));}g.test('scalars').desc(`Test that scalars in private, and function storage classes can be initialized to a value.`).params(u =>u.combine('addressSpace', ['private', 'function'] as const).combine('type', ['bool', 'f32', 'f16', 'i32', 'u32'] as const)).fn(async t => {const typeDecl = t.params.type;if (typeDecl === 'f16') {t.skipIfDeviceDoesNotHaveFeature('shader-f16');}const testValue = Type[typeDecl].create(5).wgsl();const comparison = `if (testVar != ${testValue}) {atomicStore(&output.failed, 1u);}`;const wgsl = generateShader(t.params.type === 'f16',t.params.addressSpace,typeDecl,testValue,comparison);await run(t, wgsl);});g.test('vec').desc(`Test that vectors in private, and function storage classes can be initialized to a value.`).params(u =>u.combine('addressSpace', ['private', 'function'] as const).combine('type', ['bool', 'f32', 'f16', 'i32', 'u32'] as const).combine('count', [2, 3, 4] as const)).fn(async t => {if (t.params.type === 'f16') {t.skipIfDeviceDoesNotHaveFeature('shader-f16');}const typeDecl = `vec${t.params.count}<${t.params.type}>`;const testValue = `${typeDecl}(${Type[t.params.type].create(5).wgsl()})`;const comparison = `if (!all(testVar == ${testValue})) {atomicStore(&output.failed, 1u);}`;const wgsl = generateShader(t.params.type === 'f16',t.params.addressSpace,typeDecl,testValue,comparison);await run(t, wgsl);});g.test('mat').desc(`Test that matrices in private, and function storage classes can be initialized to a value.`).params(u =>u.combine('addressSpace', ['private', 'function'] as const).combine('type', ['f32', 'f16'] as const).beginSubcases().combine('c', [2, 3, 4] as const).combine('r', [2, 3, 4] as const)).fn(async t => {if (t.params.type === 'f16') {t.skipIfDeviceDoesNotHaveFeature('shader-f16');}const typeDecl = `mat${t.params.c}x${t.params.r}<${t.params.type}>`;const testScalarValue = Type[t.params.type].create(5).wgsl();let testValue = `${typeDecl}(`;for (let c = 0; c < t.params.c; c++) {for (let r = 0; r < t.params.r; r++) {testValue += `${testScalarValue},`;}}testValue += ')';const comparison = `for ( var i = 0; i < ${t.params.c}; i++) {for (var k = 0; k < ${t.params.r}; k++) {if (testVar[i][k] != ${testScalarValue}) {atomicStore(&output.failed, 1u);}}}`;const wgsl = generateShader(t.params.type === 'f16',t.params.addressSpace,typeDecl,testValue,comparison);await run(t, wgsl);});g.test('array').desc(`Test that arrays in private, and function storage classes can be initialized to a value.`).params(u =>u.combine('addressSpace', ['private', 'function'] as const).combine('type', ['bool', 'i32', 'u32', 'f32', 'f16'] as const)).fn(async t => {if (t.params.type === 'f16') {t.skipIfDeviceDoesNotHaveFeature('shader-f16');}const arraySize = 4;const typeDecl = `array<${t.params.type}, ${arraySize}>`;const testScalarValue = Type[t.params.type].create(5).wgsl();let testValue = `${typeDecl}(`;for (let i = 0; i < arraySize; i++) {testValue += `${testScalarValue},`;}testValue += ')';const comparison = `for ( var i = 0; i < ${arraySize}; i++) {if (testVar[i] != ${testScalarValue}) {atomicStore(&output.failed, 1u);}}`;const wgsl = generateShader(t.params.type === 'f16',t.params.addressSpace,typeDecl,testValue,comparison);await run(t, wgsl);});g.test('array,nested').desc(`Test that arrays in private, and function storage classes can be initialized to a value.`).params(u =>u.combine('addressSpace', ['private', 'function'] as const).combine('type', ['bool', 'i32', 'u32', 'f32', 'f16'] as const)).fn(async t => {if (t.params.type === 'f16') {t.skipIfDeviceDoesNotHaveFeature('shader-f16');}const arraySize = 4;const innerDecl = `array<${t.params.type}, ${arraySize}>`;const typeDecl = `array<${innerDecl}, ${arraySize}>`;const testScalarValue = Type[t.params.type].create(5).wgsl();let testValue = `${typeDecl}(`;for (let i = 0; i < arraySize; i++) {testValue += `${innerDecl}(`;for (let j = 0; j < arraySize; j++) {testValue += `${testScalarValue},`;}testValue += `),`;}testValue += ')';const comparison = `for ( var i = 0; i < ${arraySize}; i++) {for ( var k = 0; k < ${arraySize}; k++) {if (testVar[i][k] != ${testScalarValue}) {atomicStore(&output.failed, 1u);}}}`;const wgsl = generateShader(t.params.type === 'f16',t.params.addressSpace,typeDecl,testValue,comparison);await run(t, wgsl);});g.test('struct').desc(`Test that structs in private, and function storage classes can be initialized to a value.`).params(u => u.combine('addressSpace', ['private', 'function'] as const)).fn(async t => {let moduleScope = `struct Output {failed : atomic<u32>}@group(0) @binding(0) var<storage, read_write> output : Output;struct A {a: i32,b: f32,}struct S {c: f32,d: A,e: array<i32, 2>,}`;const typeDecl = 'S';const testValue = 'S(5.f, A(5i, 5.f), array<i32, 2>(5i, 5i))';let functionScope = '';switch (t.params.addressSpace) {case 'private':moduleScope += `\nvar<private> testVar: ${typeDecl} = ${testValue};`;break;case 'function':functionScope += `\nvar testVar: ${typeDecl} = ${testValue};`;break;}const comparison = `if (testVar.c != 5f || testVar.d.a != 5i || testVar.d.b != 5.f || testVar.e[0] != 5i || testVar.e[1] != 5i) {atomicStore(&output.failed, 1u);}`;const wgsl = `${moduleScope}@compute @workgroup_size(1, 1, 1)fn main() {${functionScope}${comparison}}`;await run(t, wgsl);});