diff options
Diffstat (limited to 'source/val/validate_interfaces.cpp')
-rw-r--r-- | source/val/validate_interfaces.cpp | 120 |
1 files changed, 58 insertions, 62 deletions
diff --git a/source/val/validate_interfaces.cpp b/source/val/validate_interfaces.cpp index 00a5999b..7f2d6488 100644 --- a/source/val/validate_interfaces.cpp +++ b/source/val/validate_interfaces.cpp @@ -35,15 +35,12 @@ const uint32_t kMaxLocations = 4096 * 4; bool is_interface_variable(const Instruction* inst, bool is_spv_1_4) { if (is_spv_1_4) { // Starting in SPIR-V 1.4, all global variables are interface variables. - return inst->opcode() == spv::Op::OpVariable && - inst->GetOperandAs<spv::StorageClass>(2u) != - spv::StorageClass::Function; + return inst->opcode() == SpvOpVariable && + inst->word(3u) != SpvStorageClassFunction; } else { - return inst->opcode() == spv::Op::OpVariable && - (inst->GetOperandAs<spv::StorageClass>(2u) == - spv::StorageClass::Input || - inst->GetOperandAs<spv::StorageClass>(2u) == - spv::StorageClass::Output); + return inst->opcode() == SpvOpVariable && + (inst->word(3u) == SpvStorageClassInput || + inst->word(3u) == SpvStorageClassOutput); } } @@ -117,30 +114,29 @@ spv_result_t NumConsumedLocations(ValidationState_t& _, const Instruction* type, uint32_t* num_locations) { *num_locations = 0; switch (type->opcode()) { - case spv::Op::OpTypeInt: - case spv::Op::OpTypeFloat: + case SpvOpTypeInt: + case SpvOpTypeFloat: // Scalars always consume a single location. *num_locations = 1; break; - case spv::Op::OpTypeVector: + case SpvOpTypeVector: // 3- and 4-component 64-bit vectors consume two locations. - if ((_.ContainsSizedIntOrFloatType(type->id(), spv::Op::OpTypeInt, 64) || - _.ContainsSizedIntOrFloatType(type->id(), spv::Op::OpTypeFloat, - 64)) && + if ((_.ContainsSizedIntOrFloatType(type->id(), SpvOpTypeInt, 64) || + _.ContainsSizedIntOrFloatType(type->id(), SpvOpTypeFloat, 64)) && (type->GetOperandAs<uint32_t>(2) > 2)) { *num_locations = 2; } else { *num_locations = 1; } break; - case spv::Op::OpTypeMatrix: + case SpvOpTypeMatrix: // Matrices consume locations equal to the underlying vector type for // each column. NumConsumedLocations(_, _.FindDef(type->GetOperandAs<uint32_t>(1)), num_locations); *num_locations *= type->GetOperandAs<uint32_t>(2); break; - case spv::Op::OpTypeArray: { + case SpvOpTypeArray: { // Arrays consume locations equal to the underlying type times the number // of elements in the vector. NumConsumedLocations(_, _.FindDef(type->GetOperandAs<uint32_t>(1)), @@ -154,9 +150,9 @@ spv_result_t NumConsumedLocations(ValidationState_t& _, const Instruction* type, if (is_int && is_const) *num_locations *= value; break; } - case spv::Op::OpTypeStruct: { + case SpvOpTypeStruct: { // Members cannot have location decorations at this point. - if (_.HasDecoration(type->id(), spv::Decoration::Location)) { + if (_.HasDecoration(type->id(), SpvDecorationLocation)) { return _.diag(SPV_ERROR_INVALID_DATA, type) << _.VkErrorID(4918) << "Members cannot be assigned a location"; } @@ -186,8 +182,8 @@ spv_result_t NumConsumedLocations(ValidationState_t& _, const Instruction* type, uint32_t NumConsumedComponents(ValidationState_t& _, const Instruction* type) { uint32_t num_components = 0; switch (type->opcode()) { - case spv::Op::OpTypeInt: - case spv::Op::OpTypeFloat: + case SpvOpTypeInt: + case SpvOpTypeFloat: // 64-bit types consume two components. if (type->GetOperandAs<uint32_t>(1) == 64) { num_components = 2; @@ -195,7 +191,7 @@ uint32_t NumConsumedComponents(ValidationState_t& _, const Instruction* type) { num_components = 1; } break; - case spv::Op::OpTypeVector: + case SpvOpTypeVector: // Vectors consume components equal to the underlying type's consumption // times the number of elements in the vector. Note that 3- and 4-element // vectors cannot have a component decoration (i.e. assumed to be zero). @@ -203,7 +199,7 @@ uint32_t NumConsumedComponents(ValidationState_t& _, const Instruction* type) { NumConsumedComponents(_, _.FindDef(type->GetOperandAs<uint32_t>(1))); num_components *= type->GetOperandAs<uint32_t>(2); break; - case spv::Op::OpTypeArray: + case SpvOpTypeArray: // Skip the array. return NumConsumedComponents(_, _.FindDef(type->GetOperandAs<uint32_t>(1))); @@ -222,10 +218,10 @@ spv_result_t GetLocationsForVariable( ValidationState_t& _, const Instruction* entry_point, const Instruction* variable, std::unordered_set<uint32_t>* locations, std::unordered_set<uint32_t>* output_index1_locations) { - const bool is_fragment = entry_point->GetOperandAs<spv::ExecutionModel>(0) == - spv::ExecutionModel::Fragment; + const bool is_fragment = entry_point->GetOperandAs<SpvExecutionModel>(0) == + SpvExecutionModelFragment; const bool is_output = - variable->GetOperandAs<spv::StorageClass>(2) == spv::StorageClass::Output; + variable->GetOperandAs<SpvStorageClass>(2) == SpvStorageClassOutput; auto ptr_type_id = variable->GetOperandAs<uint32_t>(0); auto ptr_type = _.FindDef(ptr_type_id); auto type_id = ptr_type->GetOperandAs<uint32_t>(2); @@ -244,21 +240,21 @@ spv_result_t GetLocationsForVariable( bool has_per_task_nv = false; bool has_per_vertex_khr = false; for (auto& dec : _.id_decorations(variable->id())) { - if (dec.dec_type() == spv::Decoration::Location) { + if (dec.dec_type() == SpvDecorationLocation) { if (has_location && dec.params()[0] != location) { return _.diag(SPV_ERROR_INVALID_DATA, variable) << "Variable has conflicting location decorations"; } has_location = true; location = dec.params()[0]; - } else if (dec.dec_type() == spv::Decoration::Component) { + } else if (dec.dec_type() == SpvDecorationComponent) { if (has_component && dec.params()[0] != component) { return _.diag(SPV_ERROR_INVALID_DATA, variable) << "Variable has conflicting component decorations"; } has_component = true; component = dec.params()[0]; - } else if (dec.dec_type() == spv::Decoration::Index) { + } else if (dec.dec_type() == SpvDecorationIndex) { if (!is_output || !is_fragment) { return _.diag(SPV_ERROR_INVALID_DATA, variable) << "Index can only be applied to Fragment output variables"; @@ -269,22 +265,22 @@ spv_result_t GetLocationsForVariable( } has_index = true; index = dec.params()[0]; - } else if (dec.dec_type() == spv::Decoration::BuiltIn) { + } else if (dec.dec_type() == SpvDecorationBuiltIn) { // Don't check built-ins. return SPV_SUCCESS; - } else if (dec.dec_type() == spv::Decoration::Patch) { + } else if (dec.dec_type() == SpvDecorationPatch) { has_patch = true; - } else if (dec.dec_type() == spv::Decoration::PerTaskNV) { + } else if (dec.dec_type() == SpvDecorationPerTaskNV) { has_per_task_nv = true; - } else if (dec.dec_type() == spv::Decoration::PerVertexKHR) { + } else if (dec.dec_type() == SpvDecorationPerVertexKHR) { if (!is_fragment) { return _.diag(SPV_ERROR_INVALID_DATA, variable) << _.VkErrorID(6777) << "PerVertexKHR can only be applied to Fragment Execution " "Models"; } - if (type->opcode() != spv::Op::OpTypeArray && - type->opcode() != spv::Op::OpTypeRuntimeArray) { + if (type->opcode() != SpvOpTypeArray && + type->opcode() != SpvOpTypeRuntimeArray) { return _.diag(SPV_ERROR_INVALID_DATA, variable) << _.VkErrorID(6778) << "PerVertexKHR must be declared as arrays"; @@ -297,28 +293,28 @@ spv_result_t GetLocationsForVariable( // tessellation control, evaluation and geometry per-vertex inputs have a // layer of arraying that is not included in interface matching. bool is_arrayed = false; - switch (entry_point->GetOperandAs<spv::ExecutionModel>(0)) { - case spv::ExecutionModel::TessellationControl: + switch (entry_point->GetOperandAs<SpvExecutionModel>(0)) { + case SpvExecutionModelTessellationControl: if (!has_patch) { is_arrayed = true; } break; - case spv::ExecutionModel::TessellationEvaluation: + case SpvExecutionModelTessellationEvaluation: if (!is_output && !has_patch) { is_arrayed = true; } break; - case spv::ExecutionModel::Geometry: + case SpvExecutionModelGeometry: if (!is_output) { is_arrayed = true; } break; - case spv::ExecutionModel::Fragment: + case SpvExecutionModelFragment: if (!is_output && has_per_vertex_khr) { is_arrayed = true; } break; - case spv::ExecutionModel::MeshNV: + case SpvExecutionModelMeshNV: if (is_output && !has_per_task_nv) { is_arrayed = true; } @@ -328,21 +324,21 @@ spv_result_t GetLocationsForVariable( } // Unpack arrayness. - if (is_arrayed && (type->opcode() == spv::Op::OpTypeArray || - type->opcode() == spv::Op::OpTypeRuntimeArray)) { + if (is_arrayed && (type->opcode() == SpvOpTypeArray || + type->opcode() == SpvOpTypeRuntimeArray)) { type_id = type->GetOperandAs<uint32_t>(1); type = _.FindDef(type_id); } - if (type->opcode() == spv::Op::OpTypeStruct) { + if (type->opcode() == SpvOpTypeStruct) { // Don't check built-ins. - if (_.HasDecoration(type_id, spv::Decoration::BuiltIn)) return SPV_SUCCESS; + if (_.HasDecoration(type_id, SpvDecorationBuiltIn)) return SPV_SUCCESS; } // Only block-decorated structs don't need a location on the variable. - const bool is_block = _.HasDecoration(type_id, spv::Decoration::Block); + const bool is_block = _.HasDecoration(type_id, SpvDecorationBlock); if (!has_location && !is_block) { - const auto vuid = (type->opcode() == spv::Op::OpTypeStruct) ? 4917 : 4916; + const auto vuid = (type->opcode() == SpvOpTypeStruct) ? 4917 : 4916; return _.diag(SPV_ERROR_INVALID_DATA, variable) << _.VkErrorID(vuid) << "Variable must be decorated with a location"; } @@ -355,7 +351,7 @@ spv_result_t GetLocationsForVariable( uint32_t array_size = 1; // If the variable is still arrayed, mark the locations/components per // index. - if (type->opcode() == spv::Op::OpTypeArray) { + if (type->opcode() == SpvOpTypeArray) { // Determine the array size if possible and get the element type. std::tie(is_int, is_const, array_size) = _.EvalInt32IfConst(type->GetOperandAs<uint32_t>(2)); @@ -403,7 +399,7 @@ spv_result_t GetLocationsForVariable( std::unordered_map<uint32_t, uint32_t> member_locations; std::unordered_map<uint32_t, uint32_t> member_components; for (auto& dec : _.id_decorations(type_id)) { - if (dec.dec_type() == spv::Decoration::Location) { + if (dec.dec_type() == SpvDecorationLocation) { auto where = member_locations.find(dec.struct_member_index()); if (where == member_locations.end()) { member_locations[dec.struct_member_index()] = dec.params()[0]; @@ -412,7 +408,7 @@ spv_result_t GetLocationsForVariable( << "Member index " << dec.struct_member_index() << " has conflicting location assignments"; } - } else if (dec.dec_type() == spv::Decoration::Component) { + } else if (dec.dec_type() == SpvDecorationComponent) { auto where = member_components.find(dec.struct_member_index()); if (where == member_components.end()) { member_components[dec.struct_member_index()] = dec.params()[0]; @@ -451,7 +447,7 @@ spv_result_t GetLocationsForVariable( continue; } - if (member->opcode() == spv::Op::OpTypeArray && num_components >= 1 && + if (member->opcode() == SpvOpTypeArray && num_components >= 1 && num_components < 4) { // When an array has an element that takes less than a location in // size, calculate the used locations in a strided manner. @@ -496,12 +492,12 @@ spv_result_t ValidateLocations(ValidationState_t& _, // TODO(dneto): SPV_NV_ray_tracing also uses locations on interface variables, // in other shader stages. Similarly, the *provisional* version of // SPV_KHR_ray_tracing did as well, but not the final version. - switch (entry_point->GetOperandAs<spv::ExecutionModel>(0)) { - case spv::ExecutionModel::Vertex: - case spv::ExecutionModel::TessellationControl: - case spv::ExecutionModel::TessellationEvaluation: - case spv::ExecutionModel::Geometry: - case spv::ExecutionModel::Fragment: + switch (entry_point->GetOperandAs<SpvExecutionModel>(0)) { + case SpvExecutionModelVertex: + case SpvExecutionModelTessellationControl: + case SpvExecutionModelTessellationEvaluation: + case SpvExecutionModelGeometry: + case SpvExecutionModelFragment: break; default: return SPV_SUCCESS; @@ -515,9 +511,9 @@ spv_result_t ValidateLocations(ValidationState_t& _, for (uint32_t i = 3; i < entry_point->operands().size(); ++i) { auto interface_id = entry_point->GetOperandAs<uint32_t>(i); auto interface_var = _.FindDef(interface_id); - auto storage_class = interface_var->GetOperandAs<spv::StorageClass>(2); - if (storage_class != spv::StorageClass::Input && - storage_class != spv::StorageClass::Output) { + auto storage_class = interface_var->GetOperandAs<SpvStorageClass>(2); + if (storage_class != SpvStorageClassInput && + storage_class != SpvStorageClassOutput) { continue; } if (!seen.insert(interface_id).second) { @@ -526,7 +522,7 @@ spv_result_t ValidateLocations(ValidationState_t& _, continue; } - auto locations = (storage_class == spv::StorageClass::Input) + auto locations = (storage_class == SpvStorageClassInput) ? &input_locations : &output_locations_index0; if (auto error = GetLocationsForVariable( @@ -551,12 +547,12 @@ spv_result_t ValidateInterfaces(ValidationState_t& _) { if (spvIsVulkanEnv(_.context()->target_env)) { for (auto& inst : _.ordered_instructions()) { - if (inst.opcode() == spv::Op::OpEntryPoint) { + if (inst.opcode() == SpvOpEntryPoint) { if (auto error = ValidateLocations(_, &inst)) { return error; } } - if (inst.opcode() == spv::Op::OpTypeVoid) break; + if (inst.opcode() == SpvOpTypeVoid) break; } } |