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
2526namespace spvtools {
2627namespace 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+
532588spv_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;
0 commit comments