浏览代码

Updated spirv-tools.

Бранимир Караџић 5 年之前
父节点
当前提交
b4ea82a261

+ 1 - 1
3rdparty/spirv-tools/include/generated/build-version.inc

@@ -1 +1 @@
-"v2020.6", "SPIRV-Tools v2020.6 fecfd7c6d825bb09bd025cbd64db0ecbef420f9a"
+"v2020.6", "SPIRV-Tools v2020.6 e4fdbb82647a417e30b6da25c632bddf5cf79a58"

+ 2 - 1
3rdparty/spirv-tools/include/generated/generators.inc

@@ -24,4 +24,5 @@
 {23, "Google", "Tint Compiler", "Google Tint Compiler"},
 {23, "Google", "Tint Compiler", "Google Tint Compiler"},
 {24, "Google", "ANGLE Shader Compiler", "Google ANGLE Shader Compiler"},
 {24, "Google", "ANGLE Shader Compiler", "Google ANGLE Shader Compiler"},
 {25, "Netease Games", "Messiah Shader Compiler", "Netease Games Messiah Shader Compiler"},
 {25, "Netease Games", "Messiah Shader Compiler", "Netease Games Messiah Shader Compiler"},
-{26, "Xenia", "Xenia Emulator Microcode Translator", "Xenia Xenia Emulator Microcode Translator"},
+{26, "Xenia", "Xenia Emulator Microcode Translator", "Xenia Xenia Emulator Microcode Translator"},
+{27, "Embark Studios", "Rust GPU Compiler Backend", "Embark Studios Rust GPU Compiler Backend"},

+ 13 - 7
3rdparty/spirv-tools/source/opt/debug_info_manager.cpp

@@ -384,7 +384,8 @@ bool DebugInfoManager::IsVariableDebugDeclared(uint32_t variable_id) {
   return dbg_decl_itr != var_id_to_dbg_decl_.end();
   return dbg_decl_itr != var_id_to_dbg_decl_.end();
 }
 }
 
 
-void DebugInfoManager::KillDebugDeclares(uint32_t variable_id) {
+bool DebugInfoManager::KillDebugDeclares(uint32_t variable_id) {
+  bool modified = false;
   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
   if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
   if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
     // We intentionally copy the list of DebugDeclare instructions because
     // We intentionally copy the list of DebugDeclare instructions because
@@ -394,9 +395,11 @@ void DebugInfoManager::KillDebugDeclares(uint32_t variable_id) {
 
 
     for (auto* dbg_decl : copy_dbg_decls) {
     for (auto* dbg_decl : copy_dbg_decls) {
       context()->KillInst(dbg_decl);
       context()->KillInst(dbg_decl);
+      modified = true;
     }
     }
     var_id_to_dbg_decl_.erase(dbg_decl_itr);
     var_id_to_dbg_decl_.erase(dbg_decl_itr);
   }
   }
+  return modified;
 }
 }
 
 
 uint32_t DebugInfoManager::GetParentScope(uint32_t child_scope) {
 uint32_t DebugInfoManager::GetParentScope(uint32_t child_scope) {
@@ -514,16 +517,18 @@ Instruction* DebugInfoManager::AddDebugValueWithIndex(
   return added_dbg_value;
   return added_dbg_value;
 }
 }
 
 
-void DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
+bool DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
     Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
     Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
     Instruction* insert_pos,
     Instruction* insert_pos,
     std::unordered_set<Instruction*>* invisible_decls) {
     std::unordered_set<Instruction*>* invisible_decls) {
+  assert(scope_and_line != nullptr);
+
   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
-  if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return;
+  if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return false;
 
 
+  bool modified = false;
   for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
   for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
-    if (scope_and_line &&
-        !IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) {
+    if (!IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) {
       if (invisible_decls) invisible_decls->insert(dbg_decl_or_val);
       if (invisible_decls) invisible_decls->insert(dbg_decl_or_val);
       continue;
       continue;
     }
     }
@@ -547,10 +552,11 @@ void DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
                                    kDebugValueOperandLocalVariableIndex),
                                    kDebugValueOperandLocalVariableIndex),
                                value_id, 0, index_id, insert_before);
                                value_id, 0, index_id, insert_before);
     assert(added_dbg_value != nullptr);
     assert(added_dbg_value != nullptr);
-    added_dbg_value->UpdateDebugInfoFrom(scope_and_line ? scope_and_line
-                                                        : dbg_decl_or_val);
+    added_dbg_value->UpdateDebugInfoFrom(scope_and_line);
     AnalyzeDebugInst(added_dbg_value);
     AnalyzeDebugInst(added_dbg_value);
+    modified = true;
   }
   }
+  return modified;
 }
 }
 
 
 bool DebugInfoManager::AddDebugValueForDecl(Instruction* dbg_decl,
 bool DebugInfoManager::AddDebugValueForDecl(Instruction* dbg_decl,

+ 5 - 4
3rdparty/spirv-tools/source/opt/debug_info_manager.h

@@ -138,14 +138,15 @@ class DebugInfoManager {
   bool IsVariableDebugDeclared(uint32_t variable_id);
   bool IsVariableDebugDeclared(uint32_t variable_id);
 
 
   // Kills all debug declaration instructions with Deref whose 'Local Variable'
   // Kills all debug declaration instructions with Deref whose 'Local Variable'
-  // operand is |variable_id|.
-  void KillDebugDeclares(uint32_t variable_id);
+  // operand is |variable_id|. Returns whether it kills an instruction or not.
+  bool KillDebugDeclares(uint32_t variable_id);
 
 
   // Generates a DebugValue instruction with value |value_id| for every local
   // Generates a DebugValue instruction with value |value_id| for every local
   // variable that is in the scope of |scope_and_line| and whose memory is
   // variable that is in the scope of |scope_and_line| and whose memory is
   // |variable_id| and inserts it after the instruction |insert_pos|.
   // |variable_id| and inserts it after the instruction |insert_pos|.
-  // |invisible_decls| returns DebugDeclares invisible to |scope_and_line|.
-  void AddDebugValueIfVarDeclIsVisible(
+  // Returns whether a DebugValue is added or not. |invisible_decls| returns
+  // DebugDeclares invisible to |scope_and_line|.
+  bool AddDebugValueIfVarDeclIsVisible(
       Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
       Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
       Instruction* insert_pos,
       Instruction* insert_pos,
       std::unordered_set<Instruction*>* invisible_decls);
       std::unordered_set<Instruction*>* invisible_decls);

+ 29 - 4
3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp

@@ -148,16 +148,41 @@ bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) {
         context()->get_type_mgr()->GetType(var_inst->type_id());
         context()->get_type_mgr()->GetType(var_inst->type_id());
     const analysis::Type* store_type = var_type->AsPointer()->pointee_type();
     const analysis::Type* store_type = var_type->AsPointer()->pointee_type();
     if (!(store_type->AsStruct() || store_type->AsArray())) {
     if (!(store_type->AsStruct() || store_type->AsArray())) {
-      context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
-          nullptr, var_id, store_inst->GetSingleWordInOperand(1), store_inst,
-          nullptr);
-      context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
+      modified |= RewriteDebugDeclares(store_inst, var_id);
     }
     }
   }
   }
 
 
   return modified;
   return modified;
 }
 }
 
 
+bool LocalSingleStoreElimPass::RewriteDebugDeclares(Instruction* store_inst,
+                                                    uint32_t var_id) {
+  std::unordered_set<Instruction*> invisible_decls;
+  uint32_t value_id = store_inst->GetSingleWordInOperand(1);
+  bool modified =
+      context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
+          store_inst, var_id, value_id, store_inst, &invisible_decls);
+
+  // For cases like the argument passing for an inlined function, the value
+  // assignment is out of DebugDeclare's scope, but we have to preserve the
+  // value assignment information using DebugValue. Generally, we need
+  // ssa-rewrite analysis to decide a proper value assignment but at this point
+  // we confirm that |var_id| has a single store. We can safely add DebugValue.
+  if (!invisible_decls.empty()) {
+    BasicBlock* store_block = context()->get_instr_block(store_inst);
+    DominatorAnalysis* dominator_analysis =
+        context()->GetDominatorAnalysis(store_block->GetParent());
+    for (auto* decl : invisible_decls) {
+      if (dominator_analysis->Dominates(store_inst, decl)) {
+        context()->get_debug_info_mgr()->AddDebugValueForDecl(decl, value_id);
+        modified = true;
+      }
+    }
+  }
+  modified |= context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
+  return modified;
+}
+
 Instruction* LocalSingleStoreElimPass::FindSingleStoreAndCheckUses(
 Instruction* LocalSingleStoreElimPass::FindSingleStoreAndCheckUses(
     Instruction* var_inst, const std::vector<Instruction*>& users) const {
     Instruction* var_inst, const std::vector<Instruction*>& users) const {
   // Make sure there is exactly 1 store.
   // Make sure there is exactly 1 store.

+ 4 - 0
3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.h

@@ -94,6 +94,10 @@ class LocalSingleStoreElimPass : public Pass {
   bool RewriteLoads(Instruction* store_inst,
   bool RewriteLoads(Instruction* store_inst,
                     const std::vector<Instruction*>& uses, bool* all_rewritten);
                     const std::vector<Instruction*>& uses, bool* all_rewritten);
 
 
+  // Replaces DebugDeclares of |var_id| with DebugValues using the value
+  // assignment of |store_inst|.
+  bool RewriteDebugDeclares(Instruction* store_inst, uint32_t var_id);
+
   // Extensions supported by this pass.
   // Extensions supported by this pass.
   std::unordered_set<std::string> extensions_allowlist_;
   std::unordered_set<std::string> extensions_allowlist_;
 };
 };

+ 1 - 0
3rdparty/spirv-tools/source/opt/optimizer.cpp

@@ -161,6 +161,7 @@ Optimizer& Optimizer::RegisterPerformancePasses() {
       .RegisterPass(CreateDeadBranchElimPass())
       .RegisterPass(CreateDeadBranchElimPass())
       .RegisterPass(CreateMergeReturnPass())
       .RegisterPass(CreateMergeReturnPass())
       .RegisterPass(CreateInlineExhaustivePass())
       .RegisterPass(CreateInlineExhaustivePass())
+      .RegisterPass(CreateEliminateDeadFunctionsPass())
       .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreatePrivateToLocalPass())
       .RegisterPass(CreatePrivateToLocalPass())
       .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
       .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())

+ 85 - 21
3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp

@@ -47,6 +47,7 @@
 #include "source/opcode.h"
 #include "source/opcode.h"
 #include "source/opt/cfg.h"
 #include "source/opt/cfg.h"
 #include "source/opt/mem_pass.h"
 #include "source/opt/mem_pass.h"
+#include "source/opt/types.h"
 #include "source/util/make_unique.h"
 #include "source/util/make_unique.h"
 
 
 // Debug logging (0: Off, 1-N: Verbosity level).  Replace this with the
 // Debug logging (0: Off, 1-N: Verbosity level).  Replace this with the
@@ -326,32 +327,94 @@ void SSARewriter::ProcessStore(Instruction* inst, BasicBlock* bb) {
 }
 }
 
 
 bool SSARewriter::ProcessLoad(Instruction* inst, BasicBlock* bb) {
 bool SSARewriter::ProcessLoad(Instruction* inst, BasicBlock* bb) {
+  // Get the pointer that we are using to load from.
   uint32_t var_id = 0;
   uint32_t var_id = 0;
   (void)pass_->GetPtr(inst, &var_id);
   (void)pass_->GetPtr(inst, &var_id);
-  if (pass_->IsTargetVar(var_id)) {
-    // Get the immediate reaching definition for |var_id|.
-    uint32_t val_id = GetReachingDef(var_id, bb);
+
+  // Get the immediate reaching definition for |var_id|.
+  //
+  // In the presence of variable pointers, the reaching definition may be
+  // another pointer.  For example, the following fragment:
+  //
+  //  %2 = OpVariable %_ptr_Input_float Input
+  // %11 = OpVariable %_ptr_Function__ptr_Input_float Function
+  //       OpStore %11 %2
+  // %12 = OpLoad %_ptr_Input_float %11
+  // %13 = OpLoad %float %12
+  //
+  // corresponds to the pseudo-code:
+  //
+  // layout(location = 0) in flat float *%2
+  // float %13;
+  // float *%12;
+  // float **%11;
+  // *%11 = %2;
+  // %12 = *%11;
+  // %13 = *%12;
+  //
+  // which ultimately, should correspond to:
+  //
+  // %13 = *%2;
+  //
+  // During rewriting, the pointer %12 is found to be replaceable by %2 (i.e.,
+  // load_replacement_[12] is 2). However, when processing the load
+  // %13 = *%12, the type of %12's reaching definition is another float
+  // pointer (%2), instead of a float value.
+  //
+  // When this happens, we need to continue looking up the reaching definition
+  // chain until we get to a float value or a non-target var (i.e. a variable
+  // that cannot be SSA replaced, like %2 in this case since it is a function
+  // argument).
+  analysis::DefUseManager* def_use_mgr = pass_->context()->get_def_use_mgr();
+  analysis::TypeManager* type_mgr = pass_->context()->get_type_mgr();
+  analysis::Type* load_type = type_mgr->GetType(inst->type_id());
+  uint32_t val_id = 0;
+  bool found_reaching_def = false;
+  while (!found_reaching_def) {
+    if (!pass_->IsTargetVar(var_id)) {
+      // If the variable we are loading from is not an SSA target (globals,
+      // function parameters), do nothing.
+      return true;
+    }
+
+    val_id = GetReachingDef(var_id, bb);
     if (val_id == 0) {
     if (val_id == 0) {
       return false;
       return false;
     }
     }
 
 
-    // Schedule a replacement for the result of this load instruction with
-    // |val_id|. After all the rewriting decisions are made, every use of
-    // this load will be replaced with |val_id|.
-    const uint32_t load_id = inst->result_id();
-    assert(load_replacement_.count(load_id) == 0);
-    load_replacement_[load_id] = val_id;
-    PhiCandidate* defining_phi = GetPhiCandidate(val_id);
-    if (defining_phi) {
-      defining_phi->AddUser(load_id);
+    // If the reaching definition is a pointer type different than the type of
+    // the instruction we are analyzing, then it must be a reference to another
+    // pointer (otherwise, this would be invalid SPIRV).  We continue
+    // de-referencing it by making |val_id| be |var_id|.
+    //
+    // NOTE: if there is no reaching definition instruction, it means |val_id|
+    // is an undef.
+    Instruction* reaching_def_inst = def_use_mgr->GetDef(val_id);
+    if (reaching_def_inst &&
+        !type_mgr->GetType(reaching_def_inst->type_id())->IsSame(load_type)) {
+      var_id = val_id;
+    } else {
+      found_reaching_def = true;
     }
     }
+  }
+
+  // Schedule a replacement for the result of this load instruction with
+  // |val_id|. After all the rewriting decisions are made, every use of
+  // this load will be replaced with |val_id|.
+  uint32_t load_id = inst->result_id();
+  assert(load_replacement_.count(load_id) == 0);
+  load_replacement_[load_id] = val_id;
+  PhiCandidate* defining_phi = GetPhiCandidate(val_id);
+  if (defining_phi) {
+    defining_phi->AddUser(load_id);
+  }
 
 
 #if SSA_REWRITE_DEBUGGING_LEVEL > 1
 #if SSA_REWRITE_DEBUGGING_LEVEL > 1
-    std::cerr << "\tFound load: "
-              << inst->PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES)
-              << " (replacement for %" << load_id << " is %" << val_id << ")\n";
+  std::cerr << "\tFound load: "
+            << inst->PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES)
+            << " (replacement for %" << load_id << " is %" << val_id << ")\n";
 #endif
 #endif
-  }
+
   return true;
   return true;
 }
 }
 
 
@@ -390,8 +453,8 @@ bool SSARewriter::GenerateSSAReplacements(BasicBlock* bb) {
     }
     }
   }
   }
 
 
-  // Seal |bb|. This means that all the stores in it have been scanned and it's
-  // ready to feed them into its successors.
+  // Seal |bb|. This means that all the stores in it have been scanned and
+  // it's ready to feed them into its successors.
   SealBlock(bb);
   SealBlock(bb);
 
 
 #if SSA_REWRITE_DEBUGGING_LEVEL > 1
 #if SSA_REWRITE_DEBUGGING_LEVEL > 1
@@ -504,8 +567,8 @@ bool SSARewriter::ApplyReplacements() {
   }
   }
 
 
   // Scan uses for all inserted Phi instructions. Do this separately from the
   // Scan uses for all inserted Phi instructions. Do this separately from the
-  // registration of the Phi instruction itself to avoid trying to analyze uses
-  // of Phi instructions that have not been registered yet.
+  // registration of the Phi instruction itself to avoid trying to analyze
+  // uses of Phi instructions that have not been registered yet.
   for (Instruction* phi_inst : generated_phis) {
   for (Instruction* phi_inst : generated_phis) {
     pass_->get_def_use_mgr()->AnalyzeInstUse(&*phi_inst);
     pass_->get_def_use_mgr()->AnalyzeInstUse(&*phi_inst);
   }
   }
@@ -562,7 +625,8 @@ void SSARewriter::FinalizePhiCandidate(PhiCandidate* phi_candidate) {
   // This candidate is now completed.
   // This candidate is now completed.
   phi_candidate->MarkComplete();
   phi_candidate->MarkComplete();
 
 
-  // If |phi_candidate| is not trivial, add it to the list of Phis to generate.
+  // If |phi_candidate| is not trivial, add it to the list of Phis to
+  // generate.
   if (TryRemoveTrivialPhi(phi_candidate) == phi_candidate->result_id()) {
   if (TryRemoveTrivialPhi(phi_candidate) == phi_candidate->result_id()) {
     // If we could not remove |phi_candidate|, it means that it is complete
     // If we could not remove |phi_candidate|, it means that it is complete
     // and not trivial. Add it to the list of Phis to generate.
     // and not trivial. Add it to the list of Phis to generate.

+ 18 - 15
3rdparty/spirv-tools/source/val/validate_builtins.cpp

@@ -2603,17 +2603,19 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference(
       assert(function_id_ == 0);
       assert(function_id_ == 0);
       for (const auto em :
       for (const auto em :
            {SpvExecutionModelVertex, SpvExecutionModelTessellationEvaluation,
            {SpvExecutionModelVertex, SpvExecutionModelTessellationEvaluation,
-            SpvExecutionModelGeometry}) {
+            SpvExecutionModelGeometry, SpvExecutionModelMeshNV}) {
         id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
         id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
-            std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel,
-                      this,
-                      "Vulkan spec doesn't allow BuiltIn Layer and "
-                      "ViewportIndex to be "
-                      "used for variables with Input storage class if "
-                      "execution model is Vertex, TessellationEvaluation, or "
-                      "Geometry.",
-                      em, decoration, built_in_inst, referenced_from_inst,
-                      std::placeholders::_1));
+            std::bind(
+                &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this,
+                std::string(
+                    _.VkErrorID((operand == SpvBuiltInLayer) ? 4274 : 4406) +
+                    "Vulkan spec doesn't allow BuiltIn Layer and "
+                    "ViewportIndex to be "
+                    "used for variables with Input storage class if "
+                    "execution model is Vertex, TessellationEvaluation, "
+                    "Geometry, or MeshNV."),
+                em, decoration, built_in_inst, referenced_from_inst,
+                std::placeholders::_1));
       }
       }
     }
     }
 
 
@@ -2621,11 +2623,12 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference(
       assert(function_id_ == 0);
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this,
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this,
-          "Vulkan spec doesn't allow BuiltIn Layer and "
-          "ViewportIndex to be "
-          "used for variables with Output storage class if "
-          "execution model is "
-          "Fragment.",
+          std::string(_.VkErrorID((operand == SpvBuiltInLayer) ? 4275 : 4407) +
+                      "Vulkan spec doesn't allow BuiltIn Layer and "
+                      "ViewportIndex to be "
+                      "used for variables with Output storage class if "
+                      "execution model is "
+                      "Fragment."),
           SpvExecutionModelFragment, decoration, built_in_inst,
           SpvExecutionModelFragment, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
           referenced_from_inst, std::placeholders::_1));
     }
     }

+ 20 - 0
3rdparty/spirv-tools/source/val/validation_state.cpp

@@ -1377,6 +1377,10 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
     case 4272:
     case 4272:
       return VUID_WRAP(VUID-Layer-Layer-04272);
       return VUID_WRAP(VUID-Layer-Layer-04272);
+    case 4274:
+      return VUID_WRAP(VUID-Layer-Layer-04274);
+    case 4275:
+      return VUID_WRAP(VUID-Layer-Layer-04275);
     case 4276:
     case 4276:
       return VUID_WRAP(VUID-Layer-Layer-04276);
       return VUID_WRAP(VUID-Layer-Layer-04276);
     case 4281:
     case 4281:
@@ -1469,6 +1473,10 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
     case 4404:
     case 4404:
       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
+    case 4406:
+      return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406);
+    case 4407:
+      return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04407);
     case 4408:
     case 4408:
       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
     case 4422:
     case 4422:
@@ -1483,6 +1491,18 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
     case 4427:
     case 4427:
       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
+    case 4484:
+      return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484);
+    case 4485:
+      return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485);
+    case 4486:
+      return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486);
+    case 4490:
+      return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04490);
+    case 4491:
+      return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
+    case 4492:
+      return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
     default:
     default:
       return "";  // unknown id
       return "";  // unknown id
   };
   };