export const description = `Validation tests for matrix access expressions* Index type* Result type* Early-evaluation errors`;import { makeTestGroup } from '../../../../../common/framework/test_group.js';import { keysOf } from '../../../../../common/util/data_tables.js';import { Type } from '../../../../util/conversion.js';import { ShaderValidationTest } from '../../shader_validation_test.js';export const g = makeTestGroup(ShaderValidationTest);g.test('index_type').desc('Tests valid index types for array access expressions').params(u =>u.combine('type', ['bool','u32','i32','abstract-int','f32','f16','abstract-float','vec2i',] as const)).fn(t => {const ty = Type[t.params.type];const enable = ty.requiresF16() ? 'enable f16;' : '';const code = `${enable}fn foo() {var x = mat2x2(1,2,3,4);let tmp = x[${ty.create(0).wgsl()}];}`;const expect =t.params.type === 'i32' || t.params.type === 'u32' || t.params.type === 'abstract-int';t.expectCompileResult(expect, code);});g.test('result_type').desc('Tests that correct result type is produced for an access expression').params(u =>u.combine('element', ['f16', 'f32'] as const).combine('columns', [2, 3, 4] as const).beginSubcases().combine('rows', [2, 3, 4] as const).combine('decl', ['function', 'module'] as const)).fn(t => {const enable = t.params.element === 'f16' ? 'enable f16;' : '';const scalarTy = Type[t.params.element];const vectorTy = Type['vec'](t.params.rows, scalarTy);const matrixTy = Type['mat'](t.params.columns, t.params.rows, scalarTy);const module_decl =t.params.decl === 'module'? `@group(0) @binding(0) var<storage> x : ${matrixTy.toString()};`: ``;const function_decl = t.params.decl === 'module' ? `` : `var x : ${matrixTy.toString()};`;const code = `${enable}${module_decl}fn foo() {${function_decl}let tmp1 : ${vectorTy.toString()} = x[0];let tmp2 : ${vectorTy.toString()} = x[1];}`;t.expectCompileResult(true, code);});interface OutOfBoundsCase {code: string;result: boolean;pipeline?: boolean;value?: number;}const kOutOfBoundsCases: Record<string, OutOfBoundsCase> = {const_module_in_bounds: {code: `const x = mat2x2(1,2,3,4)[0];`,result: true,},const_module_oob_neg: {code: `const x = mat2x2(1,2,3,4)[-1];`,result: false,},const_module_oob_pos: {code: `const x = mat2x2(1,2,3,4)[2];`,result: false,},const_func_in_bounds: {code: `fn foo() {const x = mat2x2(1,2,3,4)[0];}`,result: true,},const_func_oob_neg: {code: `fn foo {const x = mat2x2(1,2,3,4)[-1];}`,result: false,},const_func_oob_pos: {code: `fn foo {const x = mat2x2(1,2,3,4)[2];}`,result: false,},override_in_bounds: {code: `override x : i32;fn y() -> u32 {let tmp = mat2x2(1,2,3,4)[x];return 0;}`,result: true,pipeline: true,value: 0,},override_oob_neg: {code: `override x : i32;fn y() -> u32 {let tmp = mat2x2(1,2,3,4)[x];return 0;}`,result: false,pipeline: true,value: -1,},override_oob_pos: {code: `override x : i32;fn y() -> u32 {let tmp = mat2x2(1,2,3,4)[x];return 0;}`,result: false,pipeline: true,value: 2,},runtime_in_bounds: {code: `fn foo() {let idx = 0;let x = mat2x2(1,2,3,4)[idx];}`,result: true,},runtime_oob_neg: {code: `fn foo() {let idx = -1;let x = mat2x2(1,2,3,4)[idx];}`,result: true,},runtime_oob_pos: {code: `fn foo() {let idx = 3;let x = mat2x2(1,2,3,4)[idx];}`,result: true,},runtime_array_const_oob_neg: {code: `@group(0) @binding(0) var<storage> x : mat2x2<f32>;fn y() -> u32 {let tmp = x[-1];return 0;}`,result: false,},runtime_array_override_oob_neg: {code: `@group(0) @binding(0) var<storage> v : mat2x2<f32>;override x : i32;fn y() -> u32 {let tmp = v[x];return 0;}`,result: false,pipeline: true,value: -1,},};g.test('early_eval_errors').desc('Tests early evaluation errors for out-of-bounds indexing').params(u => u.combine('case', keysOf(kOutOfBoundsCases))).fn(t => {const testcase = kOutOfBoundsCases[t.params.case];if (testcase.pipeline) {const v: number = testcase.value ?? 0;t.expectPipelineResult({expectedResult: testcase.result,code: testcase.code,constants: { x: v },reference: ['y()'],});} else {t.expectCompileResult(testcase.result, testcase.code);}});g.test('abstract_matrix_concrete_index').desc('Tests that a concrete index type on an abstract array remains abstract').fn(t => {const code = `const idx = 0i;const_assert mat2x2(1.11001100110011008404,1,1,1)[0i][0i] == 1.11001100110011008404;`;t.expectCompileResult(true, code);});