export const description = `Validation tests for attributes`; import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { keysOf } from '../../../../common/util/data_tables.js'; import { ShaderValidationTest } from '../shader_validation_test.js'; export const g = makeTestGroup(ShaderValidationTest); const kPossibleValues = { val: '32', expr: '30 + 2', override: 'a_override', user_func: 'a_func()', const_func: 'min(4, 8)', const: 'a_const', }; const kAttributeUsage = { align: '@align($val)', binding: '@binding($val) @group(0)', group: '@binding(1) @group($val)', id: '@id($val)', location: '@location($val)', size: '@size($val)', workgroup_size: '@workgroup_size($val, $val, $val)', }; const kAllowedUsages = { align: ['val', 'expr', 'const', 'const_func'], binding: ['val', 'expr', 'const', 'const_func'], group: ['val', 'expr', 'const', 'const_func'], id: ['val', 'expr', 'const', 'const_func'], location: ['val', 'expr', 'const', 'const_func'], size: ['val', 'expr', 'const', 'const_func'], workgroup_size: ['val', 'expr', 'const', 'const_func', 'override'], }; g.test('expressions') .desc(`Tests attributes which allow expressions`) .params(u => u.combine('value', keysOf(kPossibleValues)).combine('attribute', keysOf(kAllowedUsages)) ) .fn(t => { const attributes = { align: '', binding: '@binding(0) @group(0)', group: '@binding(1) @group(1)', id: '@id(2)', location: '@location(0)', size: '', workgroup_size: '@workgroup_size(1)', }; const val = kPossibleValues[t.params.value]; attributes[t.params.attribute] = kAttributeUsage[t.params.attribute].replace(/(\$val)/g, val); const code = ` fn a_func() -> i32 { return 4; } const a_const = -2 + 10; override a_override: i32 = 2; ${attributes.id} override my_id: i32 = 4; struct B { ${attributes.align} ${attributes.size} a: i32, } ${attributes.binding} var uniform_buffer_1: B; ${attributes.group} var uniform_buffer_2: B; @fragment fn main() -> ${attributes.location} vec4 { return vec4(.4, .2, .3, .1); } @compute ${attributes.workgroup_size} fn compute_main() {} `; const pass = kAllowedUsages[t.params.attribute].includes(t.params.value); t.expectCompileResult(pass, code); });