@@ -529,6 +529,61 @@ spv_result_t GetLocationsForVariable(
529529 return SPV_SUCCESS;
530530}
531531
532+ bool IsInterpolationDecoration (spv::Decoration dec) {
533+ return dec == spv::Decoration::PerVertexKHR || dec == spv::Decoration::Flat ||
534+ dec == spv::Decoration::NoPerspective ||
535+ dec == spv::Decoration::Sample || dec == spv::Decoration::Centroid;
536+ }
537+
538+ // Need to check Variables (or struct members) with explicit Locaiton decoration
539+ // don't mix interpolation decorations
540+ spv_result_t ValidateLocationInterpolation (
541+ ValidationState_t& _, bool is_input, const Instruction* variable,
542+ std::unordered_map<uint32_t , std::vector<spv::Decoration>>&
543+ interpolation_map) {
544+ uint32_t location = 0 ;
545+ bool has_location = false ;
546+ std::vector<spv::Decoration> interpolation_decs;
547+ for (auto & dec : _.id_decorations (variable->id ())) {
548+ spv::Decoration decoration = dec.dec_type ();
549+ if (decoration == spv::Decoration::Location) {
550+ location = dec.params ()[0 ];
551+ has_location = true ;
552+ } else if (IsInterpolationDecoration (decoration)) {
553+ interpolation_decs.push_back (decoration);
554+ }
555+ }
556+
557+ // Look for Location in a Block decorated Struct
558+ if (!has_location) {
559+ auto ptr_type_id = variable->GetOperandAs <uint32_t >(0 );
560+ auto ptr_type = _.FindDef (ptr_type_id);
561+ auto type_id = ptr_type->GetOperandAs <uint32_t >(2 );
562+ for (auto & dec : _.id_decorations (type_id)) {
563+ spv::Decoration decoration = dec.dec_type ();
564+ if (decoration == spv::Decoration::Location) {
565+ location = dec.params ()[0 ];
566+ has_location = true ;
567+ } else if (IsInterpolationDecoration (decoration)) {
568+ interpolation_decs.push_back (decoration);
569+ }
570+ }
571+ }
572+
573+ if (has_location) {
574+ auto it = interpolation_map.find (location);
575+ if (it == interpolation_map.end ()) {
576+ interpolation_map[location] = interpolation_decs;
577+ } else if (interpolation_map[location] != interpolation_decs) {
578+ return _.diag (SPV_ERROR_INVALID_DATA, variable)
579+ << _.VkErrorID (10604 ) << (is_input ? " input" : " output" )
580+ << " Location " << location
581+ << " has conflicting Interpolation decorations" ;
582+ }
583+ }
584+ return SPV_SUCCESS;
585+ }
586+
532587spv_result_t ValidateLocations (ValidationState_t& _,
533588 const Instruction* entry_point) {
534589 // According to Vulkan 14.1 only the following execution models have
@@ -554,6 +609,12 @@ spv_result_t ValidateLocations(ValidationState_t& _,
554609 std::unordered_set<uint32_t > patch_locations_index0;
555610 std::unordered_set<uint32_t > patch_locations_index1;
556611 std::unordered_set<uint32_t > seen;
612+
613+ std::unordered_map<uint32_t , std::vector<spv::Decoration>>
614+ input_interpolation;
615+ std::unordered_map<uint32_t , std::vector<spv::Decoration>>
616+ output_interpolation;
617+
557618 for (uint32_t i = 3 ; i < entry_point->operands ().size (); ++i) {
558619 auto interface_id = entry_point->GetOperandAs <uint32_t >(i);
559620 auto interface_var = _.FindDef (interface_id);
@@ -590,12 +651,17 @@ spv_result_t ValidateLocations(ValidationState_t& _,
590651 continue ;
591652 }
592653
593- auto locations = (storage_class == spv::StorageClass::Input)
594- ? &input_locations
595- : &output_locations_index0;
654+ bool is_input = storage_class == spv::StorageClass::Input;
655+ auto locations = is_input ? &input_locations : &output_locations_index0;
596656 if (auto error = GetLocationsForVariable (
597657 _, entry_point, interface_var, locations, &output_locations_index1))
598658 return error;
659+
660+ auto & interpolation_map =
661+ is_input ? input_interpolation : output_interpolation;
662+ if (auto error = ValidateLocationInterpolation (_, is_input, interface_var,
663+ interpolation_map))
664+ return error;
599665 }
600666
601667 return SPV_SUCCESS;
0 commit comments