Skip to content

Commit dc8cd21

Browse files
spirv-val: Add Location Interpolation check
1 parent ba828b2 commit dc8cd21

File tree

3 files changed

+387
-3
lines changed

3 files changed

+387
-3
lines changed

source/val/validate_interfaces.cpp

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "source/val/instruction.h"
2222
#include "source/val/validate.h"
2323
#include "source/val/validation_state.h"
24+
#include "spirv/unified1/spirv.hpp11"
2425

2526
namespace spvtools {
2627
namespace val {
@@ -529,6 +530,61 @@ spv_result_t GetLocationsForVariable(
529530
return SPV_SUCCESS;
530531
}
531532

533+
bool IsInterpolationDecoration(spv::Decoration dec) {
534+
return dec == spv::Decoration::PerVertexKHR || dec == spv::Decoration::Flat ||
535+
dec == spv::Decoration::NoPerspective ||
536+
dec == spv::Decoration::Sample || dec == spv::Decoration::Centroid;
537+
}
538+
539+
// Need to check Variables (or struct members) with explicit Locaiton decoration
540+
// don't mix interpolation decorations
541+
spv_result_t ValidateLocationInterpolation(
542+
ValidationState_t& _, bool is_input, const Instruction* variable,
543+
std::unordered_map<uint32_t, std::vector<spv::Decoration>>&
544+
interpolation_map) {
545+
uint32_t location = 0;
546+
bool has_location = false;
547+
std::vector<spv::Decoration> interpolation_decs;
548+
for (auto& dec : _.id_decorations(variable->id())) {
549+
spv::Decoration decoration = dec.dec_type();
550+
if (decoration == spv::Decoration::Location) {
551+
location = dec.params()[0];
552+
has_location = true;
553+
} else if (IsInterpolationDecoration(decoration)) {
554+
interpolation_decs.push_back(decoration);
555+
}
556+
}
557+
558+
// Look for Location in a Block decorated Struct
559+
if (!has_location) {
560+
auto ptr_type_id = variable->GetOperandAs<uint32_t>(0);
561+
auto ptr_type = _.FindDef(ptr_type_id);
562+
auto type_id = ptr_type->GetOperandAs<uint32_t>(2);
563+
for (auto& dec : _.id_decorations(type_id)) {
564+
spv::Decoration decoration = dec.dec_type();
565+
if (decoration == spv::Decoration::Location) {
566+
location = dec.params()[0];
567+
has_location = true;
568+
} else if (IsInterpolationDecoration(decoration)) {
569+
interpolation_decs.push_back(decoration);
570+
}
571+
}
572+
}
573+
574+
if (has_location) {
575+
auto it = interpolation_map.find(location);
576+
if (it == interpolation_map.end()) {
577+
interpolation_map[location] = interpolation_decs;
578+
} else if (interpolation_map[location] != interpolation_decs) {
579+
return _.diag(SPV_ERROR_INVALID_DATA, variable)
580+
<< _.VkErrorID(10604) << (is_input ? "input" : "output")
581+
<< " Location " << location
582+
<< " has conflicting Interpolation decorations";
583+
}
584+
}
585+
return SPV_SUCCESS;
586+
}
587+
532588
spv_result_t ValidateLocations(ValidationState_t& _,
533589
const Instruction* entry_point) {
534590
// According to Vulkan 14.1 only the following execution models have
@@ -554,6 +610,12 @@ spv_result_t ValidateLocations(ValidationState_t& _,
554610
std::unordered_set<uint32_t> patch_locations_index0;
555611
std::unordered_set<uint32_t> patch_locations_index1;
556612
std::unordered_set<uint32_t> seen;
613+
614+
std::unordered_map<uint32_t, std::vector<spv::Decoration>>
615+
input_interpolation;
616+
std::unordered_map<uint32_t, std::vector<spv::Decoration>>
617+
output_interpolation;
618+
557619
for (uint32_t i = 3; i < entry_point->operands().size(); ++i) {
558620
auto interface_id = entry_point->GetOperandAs<uint32_t>(i);
559621
auto interface_var = _.FindDef(interface_id);
@@ -590,12 +652,17 @@ spv_result_t ValidateLocations(ValidationState_t& _,
590652
continue;
591653
}
592654

593-
auto locations = (storage_class == spv::StorageClass::Input)
594-
? &input_locations
595-
: &output_locations_index0;
655+
bool is_input = storage_class == spv::StorageClass::Input;
656+
auto locations = is_input ? &input_locations : &output_locations_index0;
596657
if (auto error = GetLocationsForVariable(
597658
_, entry_point, interface_var, locations, &output_locations_index1))
598659
return error;
660+
661+
auto& interpolation_map =
662+
is_input ? input_interpolation : output_interpolation;
663+
if (auto error = ValidateLocationInterpolation(_, is_input, interface_var,
664+
interpolation_map))
665+
return error;
599666
}
600667

601668
return SPV_SUCCESS;

source/val/validation_state.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,6 +2536,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
25362536
return VUID_WRAP(VUID-RuntimeSpirv-Offset-10213);
25372537
case 10583:
25382538
return VUID_WRAP(VUID-StandaloneSpirv-Component-10583);
2539+
case 10604:
2540+
return VUID_WRAP(VUID-StandaloneSpirv-Input-10604);
25392541
default:
25402542
return ""; // unknown id
25412543
}

0 commit comments

Comments
 (0)