Add validation support for MeshEXT based on the spec update PR https://github.com/KhronosGroup/Vulkan-Docs/pull/2475 (#6171)
diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp index d25ebaf..2c17264 100644 --- a/source/val/validate_builtins.cpp +++ b/source/val/validate_builtins.cpp
@@ -373,6 +373,13 @@ spv_result_t ValidateMeshShadingEXTBuiltinsAtDefinition( const Decoration& decoration, const Instruction& inst); + // Used as a common method for validating MeshEXT builtins + spv_result_t ValidateMeshEXTBuiltinInterfaceRules( + const Decoration& decoration, const Instruction& inst, + spv::Op scalar_type, uint32_t array_type_vuid, uint32_t array_size_vuid, + uint32_t block_array_size_vuid, uint32_t interface_vuid, + uint32_t perprim_deco_vuid); + // The following section contains functions which are called when id defined // by |referenced_inst| is // 1. referenced by |referenced_from_inst| @@ -590,8 +597,9 @@ spv_result_t ValidateBool( const Decoration& decoration, const Instruction& inst, const std::function<spv_result_t(const std::string& message)>& diag); - spv_result_t ValidateBlockBoolOrArrayedBool( + spv_result_t ValidateBlockTypeOrArrayedType( const Decoration& decoration, const Instruction& inst, + bool& present_in_block, spv::Op expected_scalar_type, const std::function<spv_result_t(const std::string& message)>& diag); spv_result_t ValidateI( const Decoration& decoration, const Instruction& inst, @@ -675,13 +683,18 @@ // UniformConstant". std::string GetStorageClassDesc(const Instruction& inst) const; + uint64_t GetArrayLength(uint32_t interface_var_id); + // Updates inner working of the class. Is called sequentially for every // instruction. void Update(const Instruction& inst); - // Check if "inst" is an interface variable - // or type of a interface varibale of any mesh entry point - bool isMeshInterfaceVar(const Instruction& inst) { + // Check if "inst" is an interface variable or type of a interface varibale + // of any mesh entry point. Populate entry_point_interface_id with all + // entry points and interface variables that refer to the "inst" + bool isMeshInterfaceVar( + const Instruction& inst, + std::map<uint32_t, uint32_t>& entry_point_interface_id) { auto getUnderlyingTypeId = [&](const Instruction* ifxVar) { auto pointerTypeInst = _.FindDef(ifxVar->type_id()); auto typeInst = _.FindDef(pointerTypeInst->GetOperandAs<uint32_t>(2)); @@ -699,15 +712,34 @@ for (auto interface : desc.interfaces) { if (inst.opcode() == spv::Op::OpTypeStruct) { auto varInst = _.FindDef(interface); - if (inst.id() == getUnderlyingTypeId(varInst)) return true; + if (inst.id() == getUnderlyingTypeId(varInst)) { + entry_point_interface_id[entry_point] = interface; + break; + } } else if (inst.id() == interface) { - return true; + entry_point_interface_id[entry_point] = interface; + break; } } } } } - return false; + return !entry_point_interface_id.empty(); + } + + bool HasInterfaceVariableForMeshEntryPoint(spv::BuiltIn builtin, + uint32_t entry_point) { + const auto& entry_points = mesh_builtin_entry_point_.find(builtin); + if (entry_points == mesh_builtin_entry_point_.end()) return false; + + return std::any_of( + entry_points->second.begin(), entry_points->second.end(), + [entry_point](const uint32_t& ep) { return entry_point == ep; }); + } + void RegisterMeshEntryPointForBuiltin(spv::BuiltIn builtin, + uint32_t entry_point) { + auto& entry_points = mesh_builtin_entry_point_[builtin]; + entry_points.insert(entry_point); } ValidationState_t& _; @@ -730,6 +762,10 @@ // Execution models with which the current function can be called. std::set<spv::ExecutionModel> execution_models_; + + // Mesh Builtins which are part of interface variables corresponding to an + // entry point + std::map<spv::BuiltIn, std::set<uint32_t>> mesh_builtin_entry_point_; }; void BuiltInsValidator::Update(const Instruction& inst) { @@ -807,6 +843,29 @@ return ss.str(); } +uint64_t BuiltInsValidator::GetArrayLength(uint32_t interface_var_id) { + uint32_t underlying_type; + spv::StorageClass storage_class; + uint64_t array_len = -1; + const Instruction* inst = _.FindDef(interface_var_id); + if (inst->opcode() != spv::Op::OpVariable) { + return -1; + } + + if (!_.GetPointerTypeInfo(inst->type_id(), &underlying_type, + &storage_class)) { + return 0; + } + if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) { + // Get the array length + const auto length_id = _.FindDef(underlying_type)->word(3u); + if (!_.EvalConstantValUint64(length_id, &array_len)) { + return 0; + } + } + return array_len; +} + spv_result_t BuiltInsValidator::ValidateBool( const Decoration& decoration, const Instruction& inst, const std::function<spv_result_t(const std::string& message)>& diag) { @@ -823,25 +882,50 @@ return SPV_SUCCESS; } -spv_result_t BuiltInsValidator::ValidateBlockBoolOrArrayedBool( - const Decoration& decoration, const Instruction& inst, +spv_result_t BuiltInsValidator::ValidateBlockTypeOrArrayedType( + const Decoration& decoration, const Instruction& inst, bool& isBlock, + spv::Op expected_scalar_type, const std::function<spv_result_t(const std::string& message)>& diag) { uint32_t underlying_type = 0; + int64_t array_len = -1; + isBlock = true; if (spv_result_t error = GetUnderlyingType(_, decoration, inst, &underlying_type)) { return error; } // Strip the array, if present. if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) { + // Get the array length + const auto length_id = _.FindDef(underlying_type)->word(3u); + if (!_.EvalConstantValInt64(length_id, &array_len)) { + return diag(GetDefinitionDesc(decoration, inst) + + " Failed to find the array length."); + } underlying_type = _.FindDef(underlying_type)->word(2u); + isBlock = false; } else if (!_.HasDecoration(inst.id(), spv::Decoration::Block)) { // If not in array, and bool is in a struct, must be in a Block struct return diag(GetDefinitionDesc(decoration, inst) + " Scalar boolean must be in a Block."); } - if (!_.IsBoolScalarType(underlying_type)) { - return diag(GetDefinitionDesc(decoration, inst) + " is not a bool scalar."); + switch (expected_scalar_type) { + case spv::Op::OpTypeBool: + if (!_.IsBoolScalarType(underlying_type)) { + return diag(GetDefinitionDesc(decoration, inst) + + " is not a bool scalar."); + } + break; + case spv::Op::OpTypeInt: + if (!_.IsSignedIntScalarType(underlying_type)) { + return diag(GetDefinitionDesc(decoration, inst) + + " is not a signed integer scalar."); + } + break; + default: + assert(0 && "Unhandled scalar type"); + return diag(GetDefinitionDesc(decoration, inst) + + " is not a recognized scalar type."); } return SPV_SUCCESS; @@ -2189,9 +2273,22 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveIdAtDefinition( const Decoration& decoration, const Instruction& inst) { if (spvIsVulkanEnv(_.context()->target_env)) { + if (_.HasCapability(spv::Capability::MeshShadingEXT)) { + uint32_t array_type_vuid = 10595; + uint32_t interface_vuid = 0; + uint32_t array_size_vuid = 10596; + uint32_t block_array_size_vuid = 10597; + uint32_t perprim_deco_vuid = 7040; + if (spv_result_t error = ValidateMeshEXTBuiltinInterfaceRules( + decoration, inst, spv::Op::OpTypeInt, array_type_vuid, + array_size_vuid, block_array_size_vuid, interface_vuid, + perprim_deco_vuid)) { + return error; + } + } // PrimitiveId can be a per-primitive variable for mesh shader stage. // In such cases variable will have an array of 32-bit integers. - if (decoration.struct_member_index() != Decoration::kInvalidMember) { + else if (decoration.struct_member_index() != Decoration::kInvalidMember) { // This must be a 32-bit int scalar. if (spv_result_t error = ValidateI32( decoration, inst, @@ -2217,17 +2314,6 @@ return error; } } - - if (_.HasCapability(spv::Capability::MeshShadingEXT)) { - if (isMeshInterfaceVar(inst) && - !_.HasDecoration(inst.id(), spv::Decoration::PerPrimitiveEXT)) { - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << _.VkErrorID(7040) - << "According to the Vulkan spec the variable decorated with " - "Builtin PrimitiveId within the MeshEXT Execution Model must " - "also be decorated with the PerPrimitiveEXT decoration. "; - } - } } // Seed at reference checks with this built-in. @@ -2796,12 +2882,100 @@ return SPV_SUCCESS; } +spv_result_t BuiltInsValidator::ValidateMeshEXTBuiltinInterfaceRules( + const Decoration& decoration, const Instruction& inst, spv::Op scalar_type, + uint32_t array_type_vuid, uint32_t array_size_vuid, + uint32_t block_array_size_vuid, uint32_t interface_vuid, + uint32_t perprim_deco_vuid) { + bool is_block = false; + const spv::BuiltIn builtin = decoration.builtin(); + // Validate the type of the builtin and if it's part of a block or an array + if (spv_result_t error = ValidateBlockTypeOrArrayedType( + decoration, inst, is_block, scalar_type, + [this, &inst, &decoration, + &array_type_vuid](const std::string& message) -> spv_result_t { + return _.diag(SPV_ERROR_INVALID_DATA, &inst) + << _.VkErrorID(array_type_vuid) << "According to the " + << spvLogStringForEnv(_.context()->target_env) + << " spec BuiltIn " + << _.grammar().lookupOperandName( + SPV_OPERAND_TYPE_BUILT_IN, + (uint32_t)decoration.builtin()) + << " variable needs to be a either a boolean or an " + "array of booleans." + << message; + })) { + return error; + } + + // Validate that the builtin is part of the mesh interface + std::map<uint32_t, uint32_t> entry_interface_id_map; + bool found = isMeshInterfaceVar(inst, entry_interface_id_map); + if (!found) { + return _.diag(SPV_ERROR_INVALID_DATA, &inst) + << _.VkErrorID(interface_vuid) << "Declaration of builtin type" + << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, + (uint32_t)builtin) + << " not found as interface variable of any meshEXT entry point. "; + } + for (const auto& id : entry_interface_id_map) { + uint32_t entry_point_id = id.first; + uint32_t interface_var_id = id.second; + if (!HasInterfaceVariableForMeshEntryPoint(builtin, entry_point_id)) { + RegisterMeshEntryPointForBuiltin(decoration.builtin(), entry_point_id); + } else { + return _.diag(SPV_ERROR_INVALID_DATA, &inst) + << _.VkErrorID(interface_vuid) + << "There must be only one declaration of the " + << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, + (uint32_t)builtin) + << " associated with a entry point's interface. " + << GetIdDesc(*_.FindDef(interface_var_id)); + } + if (GetArrayLength(interface_var_id) != + _.GetOutputPrimitivesEXT(entry_point_id)) { + return _.diag(SPV_ERROR_INVALID_DATA, &inst) + << _.VkErrorID(is_block ? block_array_size_vuid : array_size_vuid) + << " The size of the array decorated with " + << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, + (uint32_t)builtin) + << " must match the value specified by OutputPrimitivesEXT. "; + } + } + if (!_.HasDecoration(inst.id(), spv::Decoration::PerPrimitiveEXT)) { + return _.diag(SPV_ERROR_INVALID_DATA, &inst) + << _.VkErrorID(perprim_deco_vuid) + << "According to the Vulkan spec the variable decorated with " + "Builtin " + << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, + (uint32_t)builtin) + << " within the MeshEXT Execution Model must also be " + << "decorated with the PerPrimitiveEXT decoration. "; + } + return SPV_SUCCESS; +} + spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtDefinition( const Decoration& decoration, const Instruction& inst) { if (spvIsVulkanEnv(_.context()->target_env)) { - // This can be a per-primitive variable for mesh shader stage. + if (_.HasCapability(spv::Capability::MeshShadingEXT)) { + const spv::BuiltIn label = decoration.builtin(); + uint32_t array_type_vuid = (label == spv::BuiltIn::Layer) ? 10592 : 10601; + uint32_t interface_vuid = 0; + uint32_t array_size_vuid = (label == spv::BuiltIn::Layer) ? 10593 : 10602; + uint32_t block_array_size_vuid = + (label == spv::BuiltIn::Layer) ? 10594 : 10603; + uint32_t perprim_deco_vuid = (label == spv::BuiltIn::Layer) ? 7039 : 7060; + if (spv_result_t error = ValidateMeshEXTBuiltinInterfaceRules( + decoration, inst, spv::Op::OpTypeInt, array_type_vuid, + array_size_vuid, block_array_size_vuid, interface_vuid, + perprim_deco_vuid)) { + return error; + } + } + // This can be a per-primitive variable for NV mesh shader stage. // In such cases variable will have an array of 32-bit integers. - if (decoration.struct_member_index() != Decoration::kInvalidMember) { + else if (decoration.struct_member_index() != Decoration::kInvalidMember) { // This must be a 32-bit int scalar. if (spv_result_t error = ValidateI32( decoration, inst, @@ -2820,39 +2994,23 @@ })) { return error; } - } else { - if (spv_result_t error = ValidateOptionalArrayedI32( - decoration, inst, - [this, &decoration, - &inst](const std::string& message) -> spv_result_t { - uint32_t vuid = - (decoration.builtin() == spv::BuiltIn::Layer) ? 4276 : 4408; - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << _.VkErrorID(vuid) - << "According to the Vulkan spec BuiltIn " - << _.grammar().lookupOperandName( - SPV_OPERAND_TYPE_BUILT_IN, - (uint32_t)decoration.builtin()) - << "variable needs to be a 32-bit int scalar. " - << message; - })) { - return error; - } - } - - if (isMeshInterfaceVar(inst) && - _.HasCapability(spv::Capability::MeshShadingEXT) && - !_.HasDecoration(inst.id(), spv::Decoration::PerPrimitiveEXT)) { - const spv::BuiltIn label = spv::BuiltIn(decoration.params()[0]); - uint32_t vkerrid = (label == spv::BuiltIn::Layer) ? 7039 : 7060; - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << _.VkErrorID(vkerrid) - << "According to the Vulkan spec the variable decorated with " - "Builtin " - << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, - decoration.params()[0]) - << " within the MeshEXT Execution Model must also be decorated " - "with the PerPrimitiveEXT decoration. "; + } else if (spv_result_t error = ValidateOptionalArrayedI32( + decoration, inst, + [this, &decoration, + &inst](const std::string& message) -> spv_result_t { + uint32_t vuid = + (decoration.builtin() == spv::BuiltIn::Layer) ? 4276 + : 4408; + return _.diag(SPV_ERROR_INVALID_DATA, &inst) + << _.VkErrorID(vuid) + << "According to the Vulkan spec BuiltIn " + << _.grammar().lookupOperandName( + SPV_OPERAND_TYPE_BUILT_IN, + (uint32_t)decoration.builtin()) + << "variable needs to be a 32-bit int scalar. " + << message; + })) { + return error; } } @@ -3987,30 +4145,33 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtDefinition( const Decoration& decoration, const Instruction& inst) { if (spvIsVulkanEnv(_.context()->target_env)) { - if (spv_result_t error = ValidateI32( - decoration, inst, - [this, &inst, - &decoration](const std::string& message) -> spv_result_t { - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << _.VkErrorID(4486) - << "According to the Vulkan spec BuiltIn " - << _.grammar().lookupOperandName( - SPV_OPERAND_TYPE_BUILT_IN, - (uint32_t)decoration.builtin()) - << " variable needs to be a 32-bit int scalar. " - << message; - })) { + if (_.HasCapability(spv::Capability::MeshShadingEXT)) { + uint32_t array_type_vuid = 10598; + uint32_t interface_vuid = 0; + uint32_t array_size_vuid = 10599; + uint32_t block_array_size_vuid = 10600; + uint32_t perprim_deco_vuid = 7059; + if (spv_result_t error = ValidateMeshEXTBuiltinInterfaceRules( + decoration, inst, spv::Op::OpTypeInt, array_type_vuid, + array_size_vuid, block_array_size_vuid, interface_vuid, + perprim_deco_vuid)) { + return error; + } + } else if (spv_result_t error = ValidateI32( + decoration, inst, + [this, &inst, + &decoration](const std::string& message) -> spv_result_t { + return _.diag(SPV_ERROR_INVALID_DATA, &inst) + << _.VkErrorID(4486) + << "According to the Vulkan spec BuiltIn " + << _.grammar().lookupOperandName( + SPV_OPERAND_TYPE_BUILT_IN, + (uint32_t)decoration.builtin()) + << " variable needs to be a 32-bit int scalar. " + << message; + })) { return error; } - if (isMeshInterfaceVar(inst) && - _.HasCapability(spv::Capability::MeshShadingEXT) && - !_.HasDecoration(inst.id(), spv::Decoration::PerPrimitiveEXT)) { - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << _.VkErrorID(7059) - << "The variable decorated with PrimitiveShadingRateKHR " - "within the MeshEXT Execution Model must also be " - "decorated with the PerPrimitiveEXT decoration"; - } } // Seed at reference checks with this built-in. @@ -4365,32 +4526,20 @@ return error; } break; - case spv::BuiltIn::CullPrimitiveEXT: - if (spv_result_t error = ValidateBlockBoolOrArrayedBool( - decoration, inst, - [this, &inst, &decoration, - &vuid](const std::string& message) -> spv_result_t { - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << _.VkErrorID(vuid) << "According to the " - << spvLogStringForEnv(_.context()->target_env) - << " spec BuiltIn " - << _.grammar().lookupOperandName( - SPV_OPERAND_TYPE_BUILT_IN, - (uint32_t)decoration.builtin()) - << " variable needs to be a either a boolean or an " - "array of booleans." - << message; - })) { + case spv::BuiltIn::CullPrimitiveEXT: { + uint32_t array_type_vuid = vuid; + uint32_t interface_vuid = 10591; + uint32_t array_size_vuid = 10589; + uint32_t block_array_size_vuid = 10590; + uint32_t perprim_deco_vuid = 7038; + if (spv_result_t error = ValidateMeshEXTBuiltinInterfaceRules( + decoration, inst, spv::Op::OpTypeBool, array_type_vuid, + array_size_vuid, block_array_size_vuid, interface_vuid, + perprim_deco_vuid)) { return error; } - if (!_.HasDecoration(inst.id(), spv::Decoration::PerPrimitiveEXT)) { - return _.diag(SPV_ERROR_INVALID_DATA, &inst) - << _.VkErrorID(7038) - << "The variable decorated with CullPrimitiveEXT within the " - "MeshEXT Execution Model must also be decorated with the " - "PerPrimitiveEXT decoration "; - } break; + } default: assert(0 && "Unexpected mesh EXT builtin"); }
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index 8041352..d4a8dda 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp
@@ -2634,6 +2634,30 @@ return VUID_WRAP(VUID-StandaloneSpirv-OpTypeFloat-10370); case 10583: return VUID_WRAP(VUID-StandaloneSpirv-Component-10583); + case 10589: + return VUID_WRAP(VUID-CullPrimitiveEXT-CullPrimitiveEXT-10589); + case 10590: + return VUID_WRAP(VUID-CullPrimitiveEXT-CullPrimitiveEXT-10590); + case 10591: + return VUID_WRAP(VUID-CullPrimitiveEXT-CullPrimitiveEXT-10591); + case 10592: + return VUID_WRAP(VUID-Layer-Layer-10592); + case 10593: + return VUID_WRAP(VUID-Layer-Layer-10593); + case 10594: + return VUID_WRAP(VUID-Layer-Layer-10594); + case 10598: + return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-10598); + case 10599: + return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-10599); + case 10600: + return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-10600); + case 10601: + return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-10601); + case 10602: + return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-10602); + case 10603: + return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-10603); case 10684: return VUID_WRAP(VUID-StandaloneSpirv-None-10684); case 10685:
diff --git a/test/val/val_builtins_test.cpp b/test/val/val_builtins_test.cpp index 2032ff2..c194128 100644 --- a/test/val/val_builtins_test.cpp +++ b/test/val/val_builtins_test.cpp
@@ -4666,49 +4666,6 @@ AnyVUID("VUID-PrimitiveId-PrimitiveId-07040")); } -TEST_F(ValidateBuiltIns, BadVulkanBuiltinLayerWithPerPrimitiveEXT) { - const std::string text = R"( - OpCapability MeshShadingEXT - OpCapability Shader - OpExtension "SPV_EXT_mesh_shader" - OpMemoryModel Logical GLSL450 - OpEntryPoint MeshEXT %MainMesh "MainMesh" %gl_Layer - OpExecutionMode %MainMesh OutputPrimitivesNV 1 - OpExecutionMode %MainMesh OutputVertices 3 - OpExecutionMode %MainMesh OutputTrianglesNV - OpExecutionMode %MainMesh LocalSize 1 1 1 - OpSource Slang 1 - OpName %MainMesh "MainMesh" - OpDecorate %gl_Layer BuiltIn Layer - %void = OpTypeVoid - %9 = OpTypeFunction %void - %uint = OpTypeInt 32 0 -%uint_3 = OpConstant %uint 3 -%uint_1 = OpConstant %uint 1 - %float = OpTypeFloat 32 - %int = OpTypeInt 32 1 - %int_1 = OpConstant %int 1 - %int_3 = OpConstant %int 3 -%uint_0 = OpConstant %uint 0 -%v3float = OpTypeVector %float 3 -%_ptr_Output_v3float = OpTypePointer Output %v3float -%v3uint = OpTypeVector %uint 3 -%_ptr_Output_v3uint = OpTypePointer Output %v3uint -%_ptr_Output_int = OpTypePointer Output %int -%_arr_int_int_1 = OpTypeArray %int %int_1 -%_ptr_Output__arr_int_int_1 = OpTypePointer Output %_arr_int_int_1 -%gl_Layer = OpVariable %_ptr_Output__arr_int_int_1 Output -%MainMesh = OpFunction %void None %9 - %25 = OpLabel - OpSetMeshOutputsEXT %uint_3 %uint_1 - OpReturn - OpFunctionEnd -)"; - - CompileSuccessfully(text, SPV_ENV_VULKAN_1_2); - EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2)); - EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-Layer-Layer-07039")); -} TEST_F(ValidateBuiltIns, BadVulkanBuiltinViewportIndexWithPerPrimitiveEXT) { const std::string text = R"( @@ -5214,7 +5171,7 @@ AnyVUID("VUID-PrimitivePointIndicesEXT-PrimitivePointIndicesEXT-07041")); } -TEST_F(ValidateBuiltIns, VulkanBuiltinCullPrimitiveEXT) { +TEST_F(ValidateBuiltIns, VulkanBuiltinCullPrimitiveEXTInBlock) { const std::string text = R"( OpCapability MeshShadingEXT OpExtension "SPV_EXT_mesh_shader" @@ -5255,6 +5212,50 @@ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); } +TEST_F(ValidateBuiltIns, BadVulkanBuiltinCullPrimitiveEXTBlockArraySize) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_CullPrimitiveEXT" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn CullPrimitiveEXT + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_32 = OpConstant %uint 32 + %uint_16 = OpConstant %uint 16 + %uint_1 = OpConstant %uint 1 + %int = OpTypeInt 32 1 + %bool = OpTypeBool + %gl_MeshPerPrimitiveEXT = OpTypeStruct %bool + %_arr_gl_MeshPerPrimitiveEXT_uint_16 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_16 + %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_16 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_16 + %gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_16 Output + %main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-CullPrimitiveEXT-CullPrimitiveEXT-10590")); +} + TEST_F(ValidateBuiltIns, VulkanBuiltinCullPrimitiveEXTMissingBlock) { const std::string text = R"( OpCapability MeshShadingEXT @@ -5343,7 +5344,7 @@ } // from https://github.com/KhronosGroup/SPIRV-Tools/issues/5980 -TEST_F(ValidateBuiltIns, VulkanBuiltinCullPrimitiveArrayOfBool) { +TEST_F(ValidateBuiltIns, VulkanBuiltinCullPrimitiveEXTArrayOfBool) { const std::string text = R"( OpCapability MeshShadingEXT OpExtension "SPV_EXT_mesh_shader" @@ -5393,7 +5394,7 @@ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); } -TEST_F(ValidateBuiltIns, BadVulkanBuiltinCullPrimitiveArrayOfBool) { +TEST_F(ValidateBuiltIns, BadVulkanBuiltinCullPrimitiveEXTArrayType) { const std::string text = R"( OpCapability MeshShadingEXT OpExtension "SPV_EXT_mesh_shader" @@ -5444,6 +5445,118 @@ AnyVUID("VUID-CullPrimitiveEXT-CullPrimitiveEXT-07036")); } +TEST_F(ValidateBuiltIns, BadVulkanBuiltinCullPrimitiveEXTArrayOfBoolSize) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_LocalInvocationIndex %gl_Position %4 %5 + OpExecutionMode %main LocalSize 2 1 1 + OpExecutionMode %main OutputTrianglesEXT + OpExecutionMode %main OutputVertices 2 + OpExecutionMode %main OutputPrimitivesEXT 2 + OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex + OpDecorate %gl_Position BuiltIn Position + OpDecorate %4 BuiltIn PrimitiveTriangleIndicesEXT + OpDecorate %5 BuiltIn CullPrimitiveEXT + OpDecorate %5 PerPrimitiveEXT + %uint = OpTypeInt 32 0 +%uint_2 = OpConstant %uint 2 +%uint_4 = OpConstant %uint 4 + %bool = OpTypeBool + %false = OpConstantFalse %bool +%_ptr_Input_uint = OpTypePointer Input %uint + %float = OpTypeFloat 32 +%v4float = OpTypeVector %float 4 +%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 +%_ptr_Output__arr_v4float_uint_2 = OpTypePointer Output %_arr_v4float_uint_2 +%v3uint = OpTypeVector %uint 3 +%_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2 +%_ptr_Output__arr_v3uint_uint_2 = OpTypePointer Output %_arr_v3uint_uint_2 +%_arr_bool_uint_4 = OpTypeArray %bool %uint_4 +%_ptr_Output__arr_bool_uint_4 = OpTypePointer Output %_arr_bool_uint_4 + %void = OpTypeVoid + %21 = OpTypeFunction %void +%_ptr_Output_bool = OpTypePointer Output %bool +%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input +%gl_Position = OpVariable %_ptr_Output__arr_v4float_uint_2 Output + %4 = OpVariable %_ptr_Output__arr_v3uint_uint_2 Output + %5 = OpVariable %_ptr_Output__arr_bool_uint_4 Output + %main = OpFunction %void None %21 + %23 = OpLabel + %24 = OpLoad %uint %gl_LocalInvocationIndex + OpSetMeshOutputsEXT %uint_2 %uint_2 + %25 = OpAccessChain %_ptr_Output_bool %5 %24 + OpStore %25 %false + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-CullPrimitiveEXT-CullPrimitiveEXT-10589")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinCullPrimitiveEXTInterfaceVariable) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_LocalInvocationIndex %gl_Position %4 %5 %gl_MeshPrimitivesEXT + OpExecutionMode %main LocalSize 2 1 1 + OpExecutionMode %main OutputTrianglesEXT + OpExecutionMode %main OutputVertices 2 + OpExecutionMode %main OutputPrimitivesEXT 2 + OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex + OpDecorate %gl_Position BuiltIn Position + OpDecorate %4 BuiltIn PrimitiveTriangleIndicesEXT + OpDecorate %5 BuiltIn CullPrimitiveEXT + OpDecorate %5 PerPrimitiveEXT + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn CullPrimitiveEXT + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT + %uint = OpTypeInt 32 0 +%uint_2 = OpConstant %uint 2 + %bool = OpTypeBool +%false = OpConstantFalse %bool +%_ptr_Input_uint = OpTypePointer Input %uint +%float = OpTypeFloat 32 +%v4float = OpTypeVector %float 4 +%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2 +%_ptr_Output__arr_v4float_uint_2 = OpTypePointer Output %_arr_v4float_uint_2 +%v3uint = OpTypeVector %uint 3 +%_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2 +%_ptr_Output__arr_v3uint_uint_2 = OpTypePointer Output %_arr_v3uint_uint_2 +%_arr_bool_uint_2 = OpTypeArray %bool %uint_2 +%_ptr_Output__arr_bool_uint_2 = OpTypePointer Output %_arr_bool_uint_2 + %void = OpTypeVoid + %21 = OpTypeFunction %void +%_ptr_Output_bool = OpTypePointer Output %bool +%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input +%gl_Position = OpVariable %_ptr_Output__arr_v4float_uint_2 Output + %4 = OpVariable %_ptr_Output__arr_v3uint_uint_2 Output + %5 = OpVariable %_ptr_Output__arr_bool_uint_2 Output +%gl_MeshPerPrimitiveEXT = OpTypeStruct %bool +%_arr_gl_MeshPerPrimitiveEXT_uint_2 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_2 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_2 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_2 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_2 Output + %main = OpFunction %void None %21 + %23 = OpLabel + %24 = OpLoad %uint %gl_LocalInvocationIndex + OpSetMeshOutputsEXT %uint_2 %uint_2 + %25 = OpAccessChain %_ptr_Output_bool %5 %24 + OpStore %25 %false + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-CullPrimitiveEXT-CullPrimitiveEXT-10591")); +} + TEST_F(ValidateBuiltIns, BadVulkanBuiltinCullPrimitiveEXTStorageClass) { const std::string text = R"( OpCapability MeshShadingEXT @@ -5619,6 +5732,790 @@ AnyVUID("VUID-CullPrimitiveEXT-CullPrimitiveEXT-07034")); } +TEST_F(ValidateBuiltIns, VulkanBuiltinLayerInBlockMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_Layer" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn Layer + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %int +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); +} + +TEST_F(ValidateBuiltIns, VulkanBuiltinLayerAsArrayOfIntMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_Layer + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpDecorate %gl_Layer BuiltIn Layer + OpDecorate %gl_Layer PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_Layer_uint_32 = OpTypeArray %int %uint_32 +%_ptr_Output__arr_gl_Layer_uint_32 = OpTypePointer Output %_arr_gl_Layer_uint_32 +%gl_Layer = OpVariable %_ptr_Output__arr_gl_Layer_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinLayerArrayTypeMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_Layer + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpDecorate %gl_Layer BuiltIn Layer + OpDecorate %gl_Layer PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_Layer_uint_32 = OpTypeArray %bool %uint_32 +%_ptr_Output__arr_gl_Layer_uint_32 = OpTypePointer Output %_arr_gl_Layer_uint_32 +%gl_Layer = OpVariable %_ptr_Output__arr_gl_Layer_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-Layer-Layer-10592")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinLayerInBlockMeshEXTType) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_Layer" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn Layer + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %bool +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-Layer-Layer-10592")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinLayerArrayOfIntSizeMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_Layer + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 16 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpDecorate %gl_Layer BuiltIn Layer + OpDecorate %gl_Layer PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_Layer_uint_32 = OpTypeArray %int %uint_32 +%_ptr_Output__arr_gl_Layer_uint_32 = OpTypePointer Output %_arr_gl_Layer_uint_32 +%gl_Layer = OpVariable %_ptr_Output__arr_gl_Layer_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-Layer-Layer-10593")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinLayerInBlockArraySizeMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 16 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_Layer" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn Layer + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %int +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-Layer-Layer-10594")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinLayerWithPerPrimitiveEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpCapability Shader + OpExtension "SPV_EXT_mesh_shader" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %MainMesh "MainMesh" %gl_Layer + OpExecutionMode %MainMesh OutputPrimitivesNV 1 + OpExecutionMode %MainMesh OutputVertices 3 + OpExecutionMode %MainMesh OutputTrianglesNV + OpExecutionMode %MainMesh LocalSize 1 1 1 + OpSource Slang 1 + OpName %MainMesh "MainMesh" + OpDecorate %gl_Layer BuiltIn Layer + %void = OpTypeVoid + %9 = OpTypeFunction %void + %uint = OpTypeInt 32 0 +%uint_3 = OpConstant %uint 3 +%uint_1 = OpConstant %uint 1 + %float = OpTypeFloat 32 + %int = OpTypeInt 32 1 + %int_1 = OpConstant %int 1 + %int_3 = OpConstant %int 3 +%uint_0 = OpConstant %uint 0 +%v3float = OpTypeVector %float 3 +%_ptr_Output_v3float = OpTypePointer Output %v3float +%v3uint = OpTypeVector %uint 3 +%_ptr_Output_v3uint = OpTypePointer Output %v3uint +%_ptr_Output_int = OpTypePointer Output %int +%_arr_int_int_1 = OpTypeArray %int %int_1 +%_ptr_Output__arr_int_int_1 = OpTypePointer Output %_arr_int_int_1 +%gl_Layer = OpVariable %_ptr_Output__arr_int_int_1 Output +%MainMesh = OpFunction %void None %9 + %25 = OpLabel + OpSetMeshOutputsEXT %uint_3 %uint_1 + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), AnyVUID("VUID-Layer-Layer-07039")); +} + +TEST_F(ValidateBuiltIns, VulkanBuiltinPrimitiveShadingRateKHRInBlockMeshEXT) { + const std::string text = R"( + OpCapability FragmentShadingRateKHR + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpExtension "SPV_KHR_fragment_shading_rate" +%1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_PrimitiveShadingRateEXT" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn PrimitiveShadingRateKHR + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid +%3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %int +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 +%5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); +} + +TEST_F(ValidateBuiltIns, + VulkanBuiltinPrimitiveShadingRateKHRInArrayOfIntMeshEXT) { + const std::string text = R"( + OpCapability FragmentShadingRateKHR + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpExtension "SPV_KHR_fragment_shading_rate" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_PrimitiveShadingRateEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_PrimitiveShadingRateEXT "gl_PrimitiveShadingRateEXT" + OpDecorate %gl_PrimitiveShadingRateEXT BuiltIn PrimitiveShadingRateKHR + OpDecorate %gl_PrimitiveShadingRateEXT PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_PrimitiveShadingRateEXT_uint_32 = OpTypeArray %int %uint_32 +%_ptr_Output__arr_gl_PrimitiveShadingRateEXT_uint_32 = OpTypePointer Output %_arr_gl_PrimitiveShadingRateEXT_uint_32 +%gl_PrimitiveShadingRateEXT = OpVariable %_ptr_Output__arr_gl_PrimitiveShadingRateEXT_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); +} + +TEST_F(ValidateBuiltIns, + BadVulkanBuiltinPrimitiveShadingRateKHRInArrayTypeMeshEXT) { + const std::string text = R"( + OpCapability FragmentShadingRateKHR + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpExtension "SPV_KHR_fragment_shading_rate" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_PrimitiveShadingRateEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_PrimitiveShadingRateEXT "gl_PrimitiveShadingRateEXT" + OpDecorate %gl_PrimitiveShadingRateEXT BuiltIn PrimitiveShadingRateKHR + OpDecorate %gl_PrimitiveShadingRateEXT PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_PrimitiveShadingRateEXT_uint_32 = OpTypeArray %bool %uint_32 +%_ptr_Output__arr_gl_PrimitiveShadingRateEXT_uint_32 = OpTypePointer Output %_arr_gl_PrimitiveShadingRateEXT_uint_32 +%gl_PrimitiveShadingRateEXT = OpVariable %_ptr_Output__arr_gl_PrimitiveShadingRateEXT_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT( + getDiagnosticString(), + AnyVUID("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-10598")); +} + +TEST_F(ValidateBuiltIns, + BadVulkanBuiltinPrimitiveShadingRateKHRInBlockTypeMeshEXT) { + const std::string text = R"( + OpCapability FragmentShadingRateKHR + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpExtension "SPV_KHR_fragment_shading_rate" +%1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_PrimitiveShadingRateEXT" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn PrimitiveShadingRateKHR + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid +%3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %bool +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 +%5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT( + getDiagnosticString(), + AnyVUID("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-10598")); +} + +TEST_F(ValidateBuiltIns, + BadVulkanBuiltinPrimitiveShadingRateKHRInBlockSizeMeshEXT) { + const std::string text = R"( + OpCapability FragmentShadingRateKHR + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpExtension "SPV_KHR_fragment_shading_rate" +%1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 16 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_PrimitiveShadingRateEXT" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn PrimitiveShadingRateKHR + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid +%3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %int +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 +%5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT( + getDiagnosticString(), + AnyVUID("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-10600")); +} + +TEST_F(ValidateBuiltIns, + BadVulkanBuiltinPrimitiveShadingRateKHRInArraySizeMeshEXT) { + const std::string text = R"( + OpCapability FragmentShadingRateKHR + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + OpExtension "SPV_KHR_fragment_shading_rate" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_PrimitiveShadingRateEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 16 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_PrimitiveShadingRateEXT "gl_PrimitiveShadingRateEXT" + OpDecorate %gl_PrimitiveShadingRateEXT BuiltIn PrimitiveShadingRateKHR + OpDecorate %gl_PrimitiveShadingRateEXT PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_PrimitiveShadingRateEXT_uint_32 = OpTypeArray %int %uint_32 +%_ptr_Output__arr_gl_PrimitiveShadingRateEXT_uint_32 = OpTypePointer Output %_arr_gl_PrimitiveShadingRateEXT_uint_32 +%gl_PrimitiveShadingRateEXT = OpVariable %_ptr_Output__arr_gl_PrimitiveShadingRateEXT_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT( + getDiagnosticString(), + AnyVUID("VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-10599")); +} + +TEST_F(ValidateBuiltIns, VulkanBuiltinViewportIndexInBlockMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" +%1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_ViewportIndex" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn ViewportIndex + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid +%3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %int +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 +%5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); +} + +TEST_F(ValidateBuiltIns, VulkanBuiltinViewportIndexAsArrayOfIntMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_ViewportIndex + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_ViewportIndex "gl_ViewportIndex" + OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex + OpDecorate %gl_ViewportIndex PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_ViewportIndex_uint_32 = OpTypeArray %int %uint_32 +%_ptr_Output__arr_gl_ViewportIndex_uint_32 = OpTypePointer Output %_arr_gl_ViewportIndex_uint_32 +%gl_ViewportIndex = OpVariable %_ptr_Output__arr_gl_ViewportIndex_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3)); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinViewportIndexInBlockTypeMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" +%1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_ViewportIndex" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn ViewportIndex + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid +%3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %bool +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 +%5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-ViewportIndex-ViewportIndex-10601")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinViewportIndexAsArrayTypeMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_ViewportIndex + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 32 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_ViewportIndex "gl_ViewportIndex" + OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex + OpDecorate %gl_ViewportIndex PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_ViewportIndex_uint_32 = OpTypeArray %bool %uint_32 +%_ptr_Output__arr_gl_ViewportIndex_uint_32 = OpTypePointer Output %_arr_gl_ViewportIndex_uint_32 +%gl_ViewportIndex = OpVariable %_ptr_Output__arr_gl_ViewportIndex_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-ViewportIndex-ViewportIndex-10601")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinViewportIndexInBlockArraySizeMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" +%1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_MeshPrimitivesEXT + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 16 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_MeshPerPrimitiveEXT "gl_MeshPerPrimitiveEXT" + OpMemberName %gl_MeshPerPrimitiveEXT 0 "gl_ViewportIndex" + OpName %gl_MeshPrimitivesEXT "gl_MeshPrimitivesEXT" + OpDecorate %gl_MeshPerPrimitiveEXT Block + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 BuiltIn ViewportIndex + OpMemberDecorate %gl_MeshPerPrimitiveEXT 0 PerPrimitiveEXT +%void = OpTypeVoid +%3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%gl_MeshPerPrimitiveEXT = OpTypeStruct %int +%_arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypeArray %gl_MeshPerPrimitiveEXT %uint_32 +%_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 = OpTypePointer Output %_arr_gl_MeshPerPrimitiveEXT_uint_32 +%gl_MeshPrimitivesEXT = OpVariable %_ptr_Output__arr_gl_MeshPerPrimitiveEXT_uint_32 Output +%main = OpFunction %void None %3 +%5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-ViewportIndex-ViewportIndex-10603")); +} + +TEST_F(ValidateBuiltIns, BadVulkanBuiltinViewportIndexAsArrayOfIntSizeMeshEXT) { + const std::string text = R"( + OpCapability MeshShadingEXT + OpExtension "SPV_EXT_mesh_shader" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint MeshEXT %main "main" %gl_ViewportIndex + OpExecutionModeId %main LocalSizeId %uint_32 %uint_1 %uint_1 + OpExecutionMode %main OutputVertices 81 + OpExecutionMode %main OutputPrimitivesEXT 16 + OpExecutionMode %main OutputTrianglesEXT + OpSource GLSL 450 + OpSourceExtension "GL_EXT_mesh_shader" + OpName %main "main" + OpName %gl_ViewportIndex "gl_ViewportIndex" + OpDecorate %gl_ViewportIndex BuiltIn ViewportIndex + OpDecorate %gl_ViewportIndex PerPrimitiveEXT +%void = OpTypeVoid + %3 = OpTypeFunction %void +%uint = OpTypeInt 32 0 +%uint_32 = OpConstant %uint 32 +%uint_1 = OpConstant %uint 1 +%int = OpTypeInt 32 1 +%bool = OpTypeBool +%_arr_gl_ViewportIndex_uint_32 = OpTypeArray %int %uint_32 +%_ptr_Output__arr_gl_ViewportIndex_uint_32 = OpTypePointer Output %_arr_gl_ViewportIndex_uint_32 +%gl_ViewportIndex = OpVariable %_ptr_Output__arr_gl_ViewportIndex_uint_32 Output +%main = OpFunction %void None %3 + %5 = OpLabel + OpReturn + OpFunctionEnd +)"; + + CompileSuccessfully(text, SPV_ENV_VULKAN_1_3); + EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_3)); + EXPECT_THAT(getDiagnosticString(), + AnyVUID("VUID-ViewportIndex-ViewportIndex-10602")); +} + } // namespace } // namespace val } // namespace spvtools