Sfoglia il codice sorgente

Updated spirv-tools.

Бранимир Караџић 5 anni fa
parent
commit
3c4d81c3b8

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

@@ -1 +1 @@
-"v2020.7-dev", "SPIRV-Tools v2020.7-dev 5a705a115f558ea53abd7ef08456551e6d9bd42f"
+"v2020.7-dev", "SPIRV-Tools v2020.7-dev d4fbcb113c0231d993c0ca500abfc16459fce47a"

+ 20 - 11
3rdparty/spirv-tools/source/opt/desc_sroa.cpp

@@ -63,16 +63,7 @@ bool DescriptorScalarReplacement::IsCandidate(Instruction* var) {
 
   // All structures with descriptor assignments must be replaced by variables,
   // one for each of their members - with the exceptions of buffers.
-  // Buffers are represented as structures, but we shouldn't replace a buffer
-  // with its elements. All buffers have offset decorations for members of their
-  // structure types.
-  bool has_offset_decoration = false;
-  context()->get_decoration_mgr()->ForEachDecoration(
-      var_type_inst->result_id(), SpvDecorationOffset,
-      [&has_offset_decoration](const Instruction&) {
-        has_offset_decoration = true;
-      });
-  if (has_offset_decoration) {
+  if (IsTypeOfStructuredBuffer(var_type_inst)) {
     return false;
   }
 
@@ -99,6 +90,23 @@ bool DescriptorScalarReplacement::IsCandidate(Instruction* var) {
   return true;
 }
 
+bool DescriptorScalarReplacement::IsTypeOfStructuredBuffer(
+    const Instruction* type) const {
+  if (type->opcode() != SpvOpTypeStruct) {
+    return false;
+  }
+
+  // All buffers have offset decorations for members of their structure types.
+  // This is how we distinguish it from a structure of descriptors.
+  bool has_offset_decoration = false;
+  context()->get_decoration_mgr()->ForEachDecoration(
+      type->result_id(), SpvDecorationOffset,
+      [&has_offset_decoration](const Instruction&) {
+        has_offset_decoration = true;
+      });
+  return has_offset_decoration;
+}
+
 bool DescriptorScalarReplacement::ReplaceCandidate(Instruction* var) {
   std::vector<Instruction*> access_chain_work_list;
   std::vector<Instruction*> load_work_list;
@@ -368,7 +376,8 @@ uint32_t DescriptorScalarReplacement::GetNumBindingsUsedByType(
 
   // The number of bindings consumed by a structure is the sum of the bindings
   // used by its members.
-  if (type_inst->opcode() == SpvOpTypeStruct) {
+  if (type_inst->opcode() == SpvOpTypeStruct &&
+      !IsTypeOfStructuredBuffer(type_inst)) {
     uint32_t sum = 0;
     for (uint32_t i = 0; i < type_inst->NumInOperands(); i++)
       sum += GetNumBindingsUsedByType(type_inst->GetSingleWordInOperand(i));

+ 5 - 0
3rdparty/spirv-tools/source/opt/desc_sroa.h

@@ -93,6 +93,11 @@ class DescriptorScalarReplacement : public Pass {
   // bindings used by its members.
   uint32_t GetNumBindingsUsedByType(uint32_t type_id);
 
+  // Returns true if |type| is a type that could be used for a structured buffer
+  // as opposed to a type that would be used for a structure of resource
+  // descriptors.
+  bool IsTypeOfStructuredBuffer(const Instruction* type) const;
+
   // A map from an OpVariable instruction to the set of variables that will be
   // used to replace it. The entry |replacement_variables_[var][i]| is the id of
   // a variable that will be used in the place of the the ith element of the

+ 10 - 0
3rdparty/spirv-tools/source/val/validate_annotation.cpp

@@ -219,6 +219,16 @@ spv_result_t ValidateDecorate(ValidationState_t& _, const Instruction* inst) {
            << "' is not valid for the WebGPU execution environment.";
   }
 
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if ((decoration == SpvDecorationGLSLShared) ||
+        (decoration == SpvDecorationGLSLPacked)) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << _.VkErrorID(4669) << "OpDecorate decoration '"
+             << LogStringForDecoration(decoration)
+             << "' is not valid for the Vulkan execution environment.";
+    }
+  }
+
   if (DecorationTakesIdParameters(decoration)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Decorations taking ID parameters may not be used with "

+ 65 - 92
3rdparty/spirv-tools/source/val/validate_builtins.cpp

@@ -142,15 +142,28 @@ typedef enum VUIDError_ {
   VUIDErrorMax,
 } VUIDError;
 
-const static uint32_t NumRtBuiltins = 16;
+const static uint32_t NumVUIDBuiltins = 29;
 
 typedef struct {
   SpvBuiltIn builtIn;
   uint32_t vuid[VUIDErrorMax];  // execution mode, storage class, type VUIDs
-} RtBuiltinVUIDMapping;
+} BuiltinVUIDMapping;
 
-std::array<RtBuiltinVUIDMapping, NumRtBuiltins> rtBuiltinInfo = {{
+std::array<BuiltinVUIDMapping, NumVUIDBuiltins> builtinVUIDInfo = {{
     // clang-format off
+    {SpvBuiltInSubgroupEqMask,            {0,    4370, 4371}},
+    {SpvBuiltInSubgroupGeMask,            {0,    4372, 4373}},
+    {SpvBuiltInSubgroupGtMask,            {0,    4374, 4375}},
+    {SpvBuiltInSubgroupLeMask,            {0,    4376, 4377}},
+    {SpvBuiltInSubgroupLtMask,            {0,    4378, 4379}},
+    {SpvBuiltInSubgroupLocalInvocationId, {0,    4380, 4381}},
+    {SpvBuiltInSubgroupSize,              {0,    4382, 4383}},
+    {SpvBuiltInGlobalInvocationId,        {4236, 4237, 4238}},
+    {SpvBuiltInLocalInvocationId,         {4281, 4282, 4283}},
+    {SpvBuiltInNumWorkgroups,             {4296, 4297, 4298}},
+    {SpvBuiltInNumSubgroups,              {4293, 4294, 4295}},
+    {SpvBuiltInSubgroupId,                {4367, 4368, 4369}},
+    {SpvBuiltInWorkgroupId,               {4422, 4423, 4424}},
     {SpvBuiltInHitKindKHR,                {4242, 4243, 4244}},
     {SpvBuiltInHitTNV,                    {4245, 4246, 4247}},
     {SpvBuiltInInstanceCustomIndexKHR,    {4251, 4252, 4253}},
@@ -170,9 +183,9 @@ std::array<RtBuiltinVUIDMapping, NumRtBuiltins> rtBuiltinInfo = {{
     // clang-format off
 } };
 
-uint32_t GetVUIDForRTBuiltin(SpvBuiltIn builtIn, VUIDError type) {
+uint32_t GetVUIDForBuiltin(SpvBuiltIn builtIn, VUIDError type) {
   uint32_t vuid = 0;
-  for (const auto& iter: rtBuiltinInfo) {
+  for (const auto& iter: builtinVUIDInfo) {
     if (iter.builtIn == builtIn) {
       assert(type < VUIDErrorMax);
       vuid = iter.vuid[type];
@@ -2826,32 +2839,17 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference(
 spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 3,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
-              uint32_t operand = decoration.params()[0];
-              uint32_t vuid = 0;
-              switch (operand) {
-                case SpvBuiltInGlobalInvocationId:
-                  vuid = 4238;
-                  break;
-                case SpvBuiltInLocalInvocationId:
-                  vuid = 4283;
-                  break;
-                case SpvBuiltInNumWorkgroups:
-                  vuid = 4298;
-                  break;
-                case SpvBuiltInWorkgroupId:
-                  vuid = 4424;
-                  break;
-              };
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                      << _.VkErrorID(vuid) << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      operand)
+                                                      builtin)
                      << " variable needs to be a 3-component 32-bit int "
                         "vector. "
                      << message;
@@ -2869,31 +2867,16 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference(
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
-  uint32_t operand = decoration.params()[0];
   if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
-      uint32_t vuid = 0;
-      switch (operand) {
-        case SpvBuiltInGlobalInvocationId:
-          vuid = 4237;
-          break;
-        case SpvBuiltInLocalInvocationId:
-          vuid = 4282;
-          break;
-        case SpvBuiltInNumWorkgroups:
-          vuid = 4297;
-          break;
-        case SpvBuiltInWorkgroupId:
-          vuid = 4423;
-          break;
-      };
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
@@ -2907,27 +2890,12 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference(
       bool has_webgpu_model = execution_model == SpvExecutionModelGLCompute;
       if ((spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) ||
           (spvIsWebGPUEnv(_.context()->target_env) && !has_webgpu_model)) {
-        uint32_t vuid = 0;
-        switch (operand) {
-          case SpvBuiltInGlobalInvocationId:
-            vuid = 4236;
-            break;
-          case SpvBuiltInLocalInvocationId:
-            vuid = 4281;
-            break;
-          case SpvBuiltInNumWorkgroups:
-            vuid = 4296;
-            break;
-          case SpvBuiltInWorkgroupId:
-            vuid = 4422;
-            break;
-        };
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                decoration.params()[0])
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                << " to be used only with GLCompute execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -2949,23 +2917,23 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference(
 spv_result_t BuiltInsValidator::ValidateComputeI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
             decoration, inst,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid)
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      decoration.params()[0])
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                      << " variable needs to be a 32-bit int "
                         "vector. "
                      << message;
@@ -2983,14 +2951,16 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference(
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
@@ -3002,11 +2972,12 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference(
                               execution_model == SpvExecutionModelTaskNV ||
                               execution_model == SpvExecutionModelMeshNV;
       if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) {
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                decoration.params()[0])
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                << " to be used only with GLCompute execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3028,23 +2999,23 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference(
 spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
             decoration, inst,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid)
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      decoration.params()[0])
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                      << " variable needs to be a 32-bit int. " << message;
             })) {
       return error;
@@ -3053,11 +3024,12 @@ spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
     const SpvStorageClass storage_class = GetStorageClass(inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+             << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -3070,23 +3042,23 @@ spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
 spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 4,
-            [this, &decoration,
-             &inst](const std::string& message) -> spv_result_t {
+            [this, &inst, builtin](const std::string& message) -> spv_result_t {
+              uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(vuid)
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      decoration.params()[0])
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
                      << " variable needs to be a 4-component 32-bit int "
                         "vector. "
                      << message;
@@ -3097,11 +3069,12 @@ spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition(
     const SpvStorageClass storage_class = GetStorageClass(inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+             << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                              decoration.params()[0])
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -3628,7 +3601,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
                 decoration, inst,
                 [this, &inst,
                  builtin](const std::string& message) -> spv_result_t {
-                  uint32_t vuid = GetVUIDForRTBuiltin(builtin, VUIDErrorType);
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
                   return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
@@ -3650,7 +3623,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
                 decoration, inst,
                 [this, &inst,
                  builtin](const std::string& message) -> spv_result_t {
-                  uint32_t vuid = GetVUIDForRTBuiltin(builtin, VUIDErrorType);
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
                   return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
@@ -3671,7 +3644,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
                 decoration, inst, 3,
                 [this, &inst,
                  builtin](const std::string& message) -> spv_result_t {
-                  uint32_t vuid = GetVUIDForRTBuiltin(builtin, VUIDErrorType);
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
                   return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
@@ -3691,7 +3664,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
                 decoration, inst, 3,
                 [this, &inst,
                  builtin](const std::string& message) -> spv_result_t {
-                  uint32_t vuid = GetVUIDForRTBuiltin(builtin, VUIDErrorType);
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
                   return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
@@ -3711,7 +3684,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
                 decoration, inst, 3, 4,
                 [this, &inst,
                  builtin](const std::string& message) -> spv_result_t {
-                  uint32_t vuid = GetVUIDForRTBuiltin(builtin, VUIDErrorType);
+                  uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
                   return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
@@ -3744,7 +3717,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
     const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
     if (storage_class != SpvStorageClassMax &&
         storage_class != SpvStorageClassInput) {
-      uint32_t vuid = GetVUIDForRTBuiltin(builtin, VUIDErrorStorageClass);
+      uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3757,7 +3730,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
 
     for (const SpvExecutionModel execution_model : execution_models_) {
       if (!IsExecutionModelValidForRtBuiltIn(builtin, execution_model)) {
-        uint32_t vuid = GetVUIDForRTBuiltin(builtin, VUIDErrorExecutionModel);
+        uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid) << "Vulkan spec does not allow BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,

+ 13 - 2
3rdparty/spirv-tools/source/val/validate_decorations.cpp

@@ -1260,7 +1260,8 @@ spv_result_t CheckVulkanMemoryModelDeprecatedDecorations(
 // decorations.  Otherwise emits a diagnostic and returns something other than
 // SPV_SUCCESS.
 spv_result_t CheckFPRoundingModeForShaders(ValidationState_t& vstate,
-                                           const Instruction& inst) {
+                                           const Instruction& inst,
+                                           const Decoration& decoration) {
   // Validates width-only conversion instruction for floating-point object
   // i.e., OpFConvert
   if (inst.opcode() != SpvOpFConvert) {
@@ -1270,6 +1271,15 @@ spv_result_t CheckFPRoundingModeForShaders(ValidationState_t& vstate,
               "object.";
   }
 
+  if (spvIsVulkanEnv(vstate.context()->target_env)) {
+    const auto mode = decoration.params()[0];
+    if ((mode != SpvFPRoundingModeRTE) && (mode != SpvFPRoundingModeRTZ)) {
+      return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
+             << vstate.VkErrorID(4675)
+             << "In Vulkan, the FPRoundingMode mode must only by RTE or RTZ.";
+    }
+  }
+
   // Validates Object operand of an OpStore
   for (const auto& use : inst.uses()) {
     const auto store = use.first;
@@ -1588,7 +1598,8 @@ spv_result_t CheckDecorationsFromDecoration(ValidationState_t& vstate) {
           break;
         case SpvDecorationFPRoundingMode:
           if (is_shader)
-            PASS_OR_BAIL(CheckFPRoundingModeForShaders(vstate, *inst));
+            PASS_OR_BAIL(
+                CheckFPRoundingModeForShaders(vstate, *inst, decoration));
           break;
         case SpvDecorationNonWritable:
           PASS_OR_BAIL(CheckNonWritableDecoration(vstate, *inst, decoration));

+ 141 - 80
3rdparty/spirv-tools/source/val/validate_image.cpp

@@ -16,8 +16,6 @@
 
 // Validates correctness of image instructions.
 
-#include "source/val/validate.h"
-
 #include <string>
 
 #include "source/diagnostic.h"
@@ -25,6 +23,7 @@
 #include "source/spirv_target_env.h"
 #include "source/util/bitutils.h"
 #include "source/val/instruction.h"
+#include "source/val/validate.h"
 #include "source/val/validate_scopes.h"
 #include "source/val/validation_state.h"
 
@@ -234,9 +233,10 @@ uint32_t GetMinCoordSize(SpvOp opcode, const ImageTypeInfo& info) {
 }
 
 // Checks ImageOperand bitfield and respective operands.
+// word_index is the index of the first word after the image-operand mask word.
 spv_result_t ValidateImageOperands(ValidationState_t& _,
                                    const Instruction* inst,
-                                   const ImageTypeInfo& info, uint32_t mask,
+                                   const ImageTypeInfo& info,
                                    uint32_t word_index) {
   static const bool kAllImageOperandsHandled = CheckAllImageOperandsHandled();
   (void)kAllImageOperandsHandled;
@@ -244,24 +244,43 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
   const SpvOp opcode = inst->opcode();
   const size_t num_words = inst->words().size();
 
-  // NonPrivate, Volatile, SignExtend, ZeroExtend take no operand words.
-  const uint32_t mask_bits_having_operands =
-      mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
-                       SpvImageOperandsVolatileTexelKHRMask |
-                       SpvImageOperandsSignExtendMask |
-                       SpvImageOperandsZeroExtendMask);
-  size_t expected_num_image_operand_words =
-      spvtools::utils::CountSetBits(mask_bits_having_operands);
-  if (mask & SpvImageOperandsGradMask) {
-    // Grad uses two words.
-    ++expected_num_image_operand_words;
-  }
+  const bool have_explicit_mask = (word_index - 1 < num_words);
+  const uint32_t mask = have_explicit_mask ? inst->word(word_index - 1) : 0u;
+
+  if (have_explicit_mask) {
+    // NonPrivate, Volatile, SignExtend, ZeroExtend take no operand words.
+    const uint32_t mask_bits_having_operands =
+        mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
+                         SpvImageOperandsVolatileTexelKHRMask |
+                         SpvImageOperandsSignExtendMask |
+                         SpvImageOperandsZeroExtendMask);
+    size_t expected_num_image_operand_words =
+        spvtools::utils::CountSetBits(mask_bits_having_operands);
+    if (mask & SpvImageOperandsGradMask) {
+      // Grad uses two words.
+      ++expected_num_image_operand_words;
+    }
 
-  if (expected_num_image_operand_words != num_words - word_index) {
+    if (expected_num_image_operand_words != num_words - word_index) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Number of image operand ids doesn't correspond to the bit "
+                "mask";
+    }
+  } else if (num_words != word_index - 1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Number of image operand ids doesn't correspond to the bit mask";
   }
 
+  if (info.multisampled & (0 == (mask & SpvImageOperandsSampleMask))) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Image Operand Sample is required for operation on "
+              "multi-sampled image";
+  }
+
+  // After this point, only set bits in the image operands mask can cause
+  // the module to be invalid.
+  if (mask == 0) return SPV_SUCCESS;
+
   if (spvtools::utils::CountSetBits(
           mask & (SpvImageOperandsOffsetMask | SpvImageOperandsConstOffsetMask |
                   SpvImageOperandsConstOffsetsMask)) > 1) {
@@ -296,10 +315,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
                 "or Cube";
     }
 
-    if (info.multisampled != 0) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Operand Bias requires 'MS' parameter to be 0";
-    }
+    // Multisampled is already checked.
   }
 
   if (mask & SpvImageOperandsLodMask) {
@@ -338,10 +354,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
                 "or Cube";
     }
 
-    if (info.multisampled != 0) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Operand Lod requires 'MS' parameter to be 0";
-    }
+    // Multisampled is already checked.
   }
 
   if (mask & SpvImageOperandsGradMask) {
@@ -374,10 +387,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
              << " components, but given " << dy_size;
     }
 
-    if (info.multisampled != 0) {
-      return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Operand Grad requires 'MS' parameter to be 0";
-    }
+    // Multisampled is already checked.
   }
 
   if (mask & SpvImageOperandsConstOffsetMask) {
@@ -613,12 +623,12 @@ spv_result_t ValidateImageCommon(ValidationState_t& _, const Instruction* inst,
 
     if (info.multisampled != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Image 'MS' parameter to be 0";
+             << "Expected Image 'MS' parameter to be 0";
     }
 
     if (info.arrayed != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Image Image 'arrayed' parameter to be 0";
+             << "Expected Image 'arrayed' parameter to be 0";
     }
   }
 
@@ -736,16 +746,26 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
            << "Corrupt image type definition";
   }
 
+  if (_.IsIntScalarType(info.sampled_type) &&
+      (64 == _.GetBitWidth(info.sampled_type)) &&
+      !_.HasCapability(SpvCapabilityInt64ImageEXT)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Capability Int64ImageEXT is required when using Sampled Type of "
+              "64-bit int";
+  }
+
   const auto target_env = _.context()->target_env;
   if (spvIsVulkanEnv(target_env)) {
     if ((!_.IsFloatScalarType(info.sampled_type) &&
          !_.IsIntScalarType(info.sampled_type)) ||
-        (32 != _.GetBitWidth(info.sampled_type) &&
-         (64 != _.GetBitWidth(info.sampled_type) ||
-          !_.HasCapability(SpvCapabilityInt64ImageEXT)))) {
+        ((32 != _.GetBitWidth(info.sampled_type)) &&
+         (64 != _.GetBitWidth(info.sampled_type))) ||
+        ((64 == _.GetBitWidth(info.sampled_type)) &&
+         _.IsFloatScalarType(info.sampled_type))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Expected Sampled Type to be a 32-bit int or float "
-                "scalar type for Vulkan environment";
+             << _.VkErrorID(4656)
+             << "Expected Sampled Type to be a 32-bit int, 64-bit int or "
+                "32-bit float scalar type for Vulkan environment";
     }
   } else if (spvIsOpenCLEnv(target_env)) {
     if (!_.IsVoidType(info.sampled_type)) {
@@ -804,7 +824,7 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
   if (spvIsVulkanEnv(target_env) || spvIsWebGPUEnv(target_env)) {
     if (info.sampled == 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << "Sampled must be 1 or 2 in the "
+             << _.VkErrorID(4657) << "Sampled must be 1 or 2 in the "
              << (spvIsVulkanEnv(target_env) ? "Vulkan" : "WebGPU")
              << " environment.";
     }
@@ -1085,6 +1105,20 @@ spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
                 "the value 0";
     }
   }
+
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if ((info.format != SpvImageFormatR64i) &&
+        (info.format != SpvImageFormatR64ui) &&
+        (info.format != SpvImageFormatR32f) &&
+        (info.format != SpvImageFormatR32i) &&
+        (info.format != SpvImageFormatR32ui)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4658)
+             << "Expected the Image Format in Image to be R64i, R64ui, R32f, "
+                "R32i, or R32ui for Vulkan environment";
+    }
+  }
+
   return SPV_SUCCESS;
 }
 
@@ -1122,6 +1156,14 @@ spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
 
   if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
 
+  if (info.multisampled) {
+    // When using image operands, the Sample image operand is required if and
+    // only if the image is multisampled (MS=1). The Sample image operand is
+    // only allowed for fetch, read, and write.
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Sampling operation is invalid for multisample image";
+  }
+
   if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
     const uint32_t texel_component_type =
         _.GetComponentType(actual_result_type);
@@ -1156,16 +1198,11 @@ spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
            << " components, but given only " << actual_coord_size;
   }
 
-  if (inst->words().size() <= 5) {
-    assert(IsImplicitLod(opcode));
-    return SPV_SUCCESS;
-  }
-
-  const uint32_t mask = inst->word(5);
+  const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
 
-  if (spvIsOpenCLEnv(_.context()->target_env)) {
-    if (opcode == SpvOpImageSampleExplicitLod) {
-      if (mask & SpvImageOperandsConstOffsetMask) {
+  if (mask & SpvImageOperandsConstOffsetMask) {
+    if (spvIsOpenCLEnv(_.context()->target_env)) {
+      if (opcode == SpvOpImageSampleExplicitLod) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "ConstOffset image operand not allowed "
                << "in the OpenCL environment.";
@@ -1174,7 +1211,7 @@ spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
   }
 
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 6))
     return result;
 
   return SPV_SUCCESS;
@@ -1209,6 +1246,14 @@ spv_result_t ValidateImageDrefLod(ValidationState_t& _,
 
   if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
 
+  if (info.multisampled) {
+    // When using image operands, the Sample image operand is required if and
+    // only if the image is multisampled (MS=1). The Sample image operand is
+    // only allowed for fetch, read, and write.
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Dref sampling operation is invalid for multisample image";
+  }
+
   if (actual_result_type != info.sampled_type) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image 'Sampled Type' to be the same as "
@@ -1235,14 +1280,8 @@ spv_result_t ValidateImageDrefLod(ValidationState_t& _,
            << "Expected Dref to be of 32-bit float type";
   }
 
-  if (inst->words().size() <= 6) {
-    assert(IsImplicitLod(opcode));
-    return SPV_SUCCESS;
-  }
-
-  const uint32_t mask = inst->word(6);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 7))
     return result;
 
   return SPV_SUCCESS;
@@ -1313,11 +1352,8 @@ spv_result_t ValidateImageFetch(ValidationState_t& _, const Instruction* inst) {
            << " components, but given only " << actual_coord_size;
   }
 
-  if (inst->words().size() <= 5) return SPV_SUCCESS;
-
-  const uint32_t mask = inst->word(5);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 6))
     return result;
 
   return SPV_SUCCESS;
@@ -1355,6 +1391,14 @@ spv_result_t ValidateImageGather(ValidationState_t& _,
            << "Corrupt image type definition";
   }
 
+  if (info.multisampled) {
+    // When using image operands, the Sample image operand is required if and
+    // only if the image is multisampled (MS=1). The Sample image operand is
+    // only allowed for fetch, read, and write.
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Gather operation is invalid for multisample image";
+  }
+
   if (opcode == SpvOpImageDrefGather || opcode == SpvOpImageSparseDrefGather ||
       _.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
     const uint32_t result_component_type =
@@ -1403,11 +1447,8 @@ spv_result_t ValidateImageGather(ValidationState_t& _,
     }
   }
 
-  if (inst->words().size() <= 6) return SPV_SUCCESS;
-
-  const uint32_t mask = inst->word(6);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 7))
     return result;
 
   return SPV_SUCCESS;
@@ -1427,14 +1468,16 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
            << " to be int or float scalar or vector type";
   }
 
-#if 0
-  // TODO([email protected]) Disabled until the spec is clarified.
-  if (_.GetDimension(actual_result_type) != 4) {
-    return _.diag(SPV_ERROR_INVALID_DATA, inst)
-           << "Expected " << GetActualResultTypeStr(opcode)
-           << " to have 4 components";
-  }
-#endif
+  const auto target_env = _.context()->target_env;
+  // Vulkan and WebGPU require the result to be a 4-element int or float
+  // vector.
+  if (spvIsVulkanEnv(target_env) || spvIsWebGPUEnv(target_env)) {
+    if (_.GetDimension(actual_result_type) != 4) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Expected " << GetActualResultTypeStr(opcode)
+             << " to have 4 components";
+    }
+  }  // Check OpenCL below, after we get the image info.
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
   if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
@@ -1448,6 +1491,29 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
            << "Corrupt image type definition";
   }
 
+  if (spvIsOpenCLEnv(target_env)) {
+    // In OpenCL, a read from a depth image returns a scalar float. In other
+    // cases, the result is always a 4-element vector.
+    // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_Env.html#_data_format_for_reading_and_writing_images
+    // https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_C.html#image-read-and-write-functions
+    // The builtins for reading depth images are:
+    //   float read_imagef(aQual image2d_depth_t image, int2 coord)
+    //   float read_imagef(aQual image2d_array_depth_t image, int4 coord)
+    if (info.depth) {
+      if (!_.IsFloatScalarType(actual_result_type)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Expected " << GetActualResultTypeStr(opcode)
+               << " from a depth image read to result in a scalar float value";
+      }
+    } else {
+      if (_.GetDimension(actual_result_type) != 4) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Expected " << GetActualResultTypeStr(opcode)
+               << " to have 4 components";
+      }
+    }
+  }
+
   if (info.dim == SpvDimSubpassData) {
     if (opcode == SpvOpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1496,12 +1562,10 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
     }
   }
 
-  if (inst->words().size() <= 5) return SPV_SUCCESS;
-
-  const uint32_t mask = inst->word(5);
+  const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
 
-  if (spvIsOpenCLEnv(_.context()->target_env)) {
-    if (mask & SpvImageOperandsConstOffsetMask) {
+  if (mask & SpvImageOperandsConstOffsetMask) {
+    if (spvIsOpenCLEnv(_.context()->target_env)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "ConstOffset image operand not allowed "
              << "in the OpenCL environment.";
@@ -1509,7 +1573,7 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
   }
 
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 6))
     return result;
 
   return SPV_SUCCESS;
@@ -1585,9 +1649,7 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
     }
   }
 
-  if (inst->words().size() <= 4) {
-    return SPV_SUCCESS;
-  } else {
+  if (inst->words().size() > 4) {
     if (spvIsOpenCLEnv(_.context()->target_env)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Optional Image Operands are not allowed in the OpenCL "
@@ -1595,9 +1657,8 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
     }
   }
 
-  const uint32_t mask = inst->word(4);
   if (spv_result_t result =
-          ValidateImageOperands(_, inst, info, mask, /* word_index = */ 5))
+          ValidateImageOperands(_, inst, info, /* word_index = */ 5))
     return result;
 
   return SPV_SUCCESS;

+ 2 - 1
3rdparty/spirv-tools/source/val/validate_memory.cpp

@@ -585,7 +585,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
       storage_class != SpvStorageClassFunction) {
     if (spvIsVulkanOrWebGPUEnv(_.context()->target_env)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpVariable, <id> '" << _.getIdName(inst->id())
+             << _.VkErrorID(4651) << "OpVariable, <id> '"
+             << _.getIdName(inst->id())
              << "', has a disallowed initializer & storage class "
              << "combination.\n"
              << "From " << spvLogStringForEnv(_.context()->target_env)

+ 2 - 2
3rdparty/spirv-tools/source/val/validate_memory_semantics.cpp

@@ -221,7 +221,7 @@ spv_result_t ValidateMemorySemantics(ValidationState_t& _,
 
     if (opcode == SpvOpMemoryBarrier && !num_memory_order_set_bits) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(4649) << spvOpcodeString(opcode)
              << ": Vulkan specification requires Memory Semantics to have "
                 "one "
                 "of the following bits set: Acquire, Release, "
@@ -231,7 +231,7 @@ spv_result_t ValidateMemorySemantics(ValidationState_t& _,
 
     if (opcode == SpvOpMemoryBarrier && !includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
-             << spvOpcodeString(opcode)
+             << _.VkErrorID(4649) << spvOpcodeString(opcode)
              << ": expected Memory Semantics to include a Vulkan-supported "
                 "storage class";
     }

+ 1 - 1
3rdparty/spirv-tools/source/val/validate_misc.cpp

@@ -56,7 +56,7 @@ spv_result_t ValidateShaderClock(ValidationState_t& _,
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
   if (is_const_int32 && value != SpvScopeSubgroup && value != SpvScopeDevice) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
-           << "Scope must be Subgroup or Device";
+           << _.VkErrorID(4652) << "Scope must be Subgroup or Device";
   }
 
   // Result Type must be a 64 - bit unsigned integer type or

+ 6 - 2
3rdparty/spirv-tools/source/val/validate_mode_setting.cpp

@@ -42,7 +42,8 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) {
     const auto entry_point_type = _.FindDef(entry_point_type_id);
     if (!entry_point_type || 3 != entry_point_type->words().size()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_point_id)
+             << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> '"
+             << _.getIdName(entry_point_id)
              << "'s function parameter count is not zero.";
     }
   }
@@ -50,7 +51,8 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) {
   auto return_type = _.FindDef(entry_point->type_id());
   if (!return_type || SpvOpTypeVoid != return_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << "OpEntryPoint Entry Point <id> '" << _.getIdName(entry_point_id)
+           << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> '"
+           << _.getIdName(entry_point_id)
            << "'s function return type is not void.";
   }
 
@@ -457,11 +459,13 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
   if (spvIsVulkanEnv(_.context()->target_env)) {
     if (mode == SpvExecutionModeOriginLowerLeft) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4653)
              << "In the Vulkan environment, the OriginLowerLeft execution mode "
                 "must not be used.";
     }
     if (mode == SpvExecutionModePixelCenterInteger) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4654)
              << "In the Vulkan environment, the PixelCenterInteger execution "
                 "mode must not be used.";
     }

+ 13 - 0
3rdparty/spirv-tools/source/val/validate_non_uniform.cpp

@@ -47,6 +47,19 @@ spv_result_t ValidateGroupNonUniformBallotBitCount(ValidationState_t& _,
                                                    "vector of four components "
                                                    "of integer type scalar";
   }
+
+  const auto group = inst->GetOperandAs<uint32_t>(3);
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if ((group != SpvGroupOperationReduce) &&
+        (group != SpvGroupOperationInclusiveScan) &&
+        (group != SpvGroupOperationExclusiveScan)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << _.VkErrorID(4685)
+             << "In Vulkan: The OpGroupNonUniformBallotBitCount group "
+                "operation must be only: Reduce, InclusiveScan, or "
+                "ExclusiveScan.";
+    }
+  }
   return SPV_SUCCESS;
 }
 

+ 1 - 1
3rdparty/spirv-tools/source/val/validate_scopes.cpp

@@ -99,7 +99,7 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _,
       if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
           value != SpvScopeSubgroup) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
-               << spvOpcodeString(opcode)
+               << _.VkErrorID(4642) << spvOpcodeString(opcode)
                << ": in Vulkan environment Execution scope is limited to "
                << "Subgroup";
       }

+ 11 - 2
3rdparty/spirv-tools/source/val/validate_type.cpp

@@ -555,8 +555,8 @@ spv_result_t ValidateTypeForwardPointer(ValidationState_t& _,
            << "Pointer type in OpTypeForwardPointer is not a pointer type.";
   }
 
-  if (inst->GetOperandAs<uint32_t>(1) !=
-      pointer_type_inst->GetOperandAs<uint32_t>(1)) {
+  const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
+  if (storage_class != pointer_type_inst->GetOperandAs<uint32_t>(1)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Storage class in OpTypeForwardPointer does not match the "
            << "pointer definition.";
@@ -569,6 +569,15 @@ spv_result_t ValidateTypeForwardPointer(ValidationState_t& _,
            << "Forward pointers must point to a structure";
   }
 
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if (storage_class != SpvStorageClassPhysicalStorageBuffer) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << _.VkErrorID(4711)
+             << "In Vulkan, OpTypeForwardPointer must have "
+             << "a storage class of PhysicalStorageBuffer.";
+    }
+  }
+
   return SPV_SUCCESS;
 }
 

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

@@ -1445,6 +1445,12 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
     case 4283:
       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
+    case 4293:
+      return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04293);
+    case 4294:
+      return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04294);
+    case 4295:
+      return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04295);
     case 4296:
       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04296);
     case 4297:
@@ -1539,6 +1545,40 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
     case 4362:
       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
+    case 4367:
+      return VUID_WRAP(VUID-SubgroupId-SubgroupId-04367);
+    case 4368:
+      return VUID_WRAP(VUID-SubgroupId-SubgroupId-04368);
+    case 4369:
+      return VUID_WRAP(VUID-SubgroupId-SubgroupId-04369);
+    case 4370:
+      return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04370);
+    case 4371:
+      return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04371);
+    case 4372:
+      return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04372);
+    case 4373:
+      return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04373);
+    case 4374:
+      return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04374);
+    case 4375:
+      return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04375);
+    case 4376:
+      return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04376);
+    case 4377:
+      return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04377);
+    case 4378:
+      return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04378);
+    case 4379:
+      return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04379);
+    case 4380:
+      return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380);
+    case 4381:
+      return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381);
+    case 4382:
+      return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04382);
+    case 4383:
+      return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04383);
     case 4387:
       return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
     case 4388:
@@ -1625,6 +1665,34 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
     case 4492:
       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
+    case 4633:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
+    case 4642:
+      return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
+    case 4649:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04649);
+    case 4651:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
+    case 4652:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpReadClockKHR-04652);
+    case 4653:
+      return VUID_WRAP(VUID-StandaloneSpirv-OriginLowerLeft-04653);
+    case 4654:
+      return VUID_WRAP(VUID-StandaloneSpirv-PixelCenterInteger-04654);
+    case 4656:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
+    case 4657:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04657);
+    case 4658:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
+    case 4669:
+      return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
+    case 4675:
+      return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
+    case 4685:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
+    case 4711:
+      return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711);
     default:
       return "";  // unknown id
   };