export const description = `Validation tests for attributes and entry point requirements`;import { makeTestGroup } from '../../../../common/framework/test_group.js';import { ShaderValidationTest } from '../shader_validation_test.js';export const g = makeTestGroup(ShaderValidationTest);g.test('missing_attribute_on_param').desc(`Test that an entry point without an IO attribute on one of its parameters is rejected.`).params(u =>u.combine('target_stage', ['', 'vertex', 'fragment', 'compute'] as const).beginSubcases()).fn(t => {const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@location(1)';const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(1)';const compute_attr = t.params.target_stage === 'compute' ? '' : '@builtin(workgroup_id)';const code = `@vertexfn vert_main(@location(0) a : f32,${vertex_attr} b : f32,@ location(2) c : f32) -> @builtin(position) vec4<f32> {return vec4<f32>();}@fragmentfn frag_main(@location(0) a : f32,${fragment_attr} b : f32,@ location(2) c : f32) {}@compute @workgroup_size(1)fn comp_main(@builtin(global_invocation_id) a : vec3<u32>,${compute_attr} b : vec3<u32>,@builtin(local_invocation_id) c : vec3<u32>) {}`;t.expectCompileResult(t.params.target_stage === '', code);});g.test('missing_attribute_on_param_struct').desc(`Test that an entry point struct parameter without an IO attribute on one of its members is rejected.`).params(u =>u.combine('target_stage', ['', 'vertex', 'fragment', 'compute'] as const).beginSubcases()).fn(t => {const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@location(1)';const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(1)';const compute_attr = t.params.target_stage === 'compute' ? '' : '@builtin(workgroup_id)';const code = `struct VertexInputs {@location(0) a : f32,${vertex_attr} b : f32,@ location(2) c : f32,};struct FragmentInputs {@location(0) a : f32,${fragment_attr} b : f32,@ location(2) c : f32,};struct ComputeInputs {@builtin(global_invocation_id) a : vec3<u32>,${compute_attr} b : vec3<u32>,@builtin(local_invocation_id) c : vec3<u32>,};@vertexfn vert_main(inputs : VertexInputs) -> @builtin(position) vec4<f32> {return vec4<f32>();}@fragmentfn frag_main(inputs : FragmentInputs) {}@compute @workgroup_size(1)fn comp_main(inputs : ComputeInputs) {}`;t.expectCompileResult(t.params.target_stage === '', code);});g.test('missing_attribute_on_return_type').desc(`Test that an entry point without an IO attribute on its return type is rejected.`).params(u => u.combine('target_stage', ['', 'vertex', 'fragment'] as const).beginSubcases()).fn(t => {const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@builtin(position)';const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(0)';const code = `@vertexfn vert_main() -> ${vertex_attr} vec4<f32> {return vec4<f32>();}@fragmentfn frag_main() -> ${fragment_attr} vec4<f32> {return vec4<f32>();}`;t.expectCompileResult(t.params.target_stage === '', code);});g.test('missing_attribute_on_return_type_struct').desc(`Test that an entry point struct return type without an IO attribute on one of its members is rejected.`).params(u => u.combine('target_stage', ['', 'vertex', 'fragment'] as const).beginSubcases()).fn(t => {const vertex_attr = t.params.target_stage === 'vertex' ? '' : '@location(1)';const fragment_attr = t.params.target_stage === 'fragment' ? '' : '@location(1)';const code = `struct VertexOutputs {@location(0) a : f32,${vertex_attr} b : f32,@builtin(position) c : vec4<f32>,};struct FragmentOutputs {@location(0) a : f32,${fragment_attr} b : f32,@ location(2) c : f32,};@vertexfn vert_main() -> VertexOutputs {return VertexOutputs();}@fragmentfn frag_main() -> FragmentOutputs {return FragmentOutputs();}`;t.expectCompileResult(t.params.target_stage === '', code);});g.test('no_entry_point_provided').desc(`Tests that a shader without an entry point is accepted`).fn(t => {t.expectCompileResult(true, 'fn main() {}');});