aboutsummaryrefslogtreecommitdiff
path: root/source/val/validate_interfaces.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/val/validate_interfaces.cpp')
-rw-r--r--source/val/validate_interfaces.cpp120
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;
}
}