Browse Source

Updated spirv-tools.

Бранимир Караџић 3 years ago
parent
commit
557b9743fb
25 changed files with 373 additions and 63 deletions
  1. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  2. 2 0
      3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
  3. 4 0
      3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
  4. 2 0
      3rdparty/spirv-tools/include/generated/extension_enum.inc
  5. 2 1
      3rdparty/spirv-tools/include/generated/generators.inc
  6. 11 3
      3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
  7. 5 0
      3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp
  8. 8 2
      3rdparty/spirv-tools/source/link/linker.cpp
  9. 1 0
      3rdparty/spirv-tools/source/opcode.cpp
  10. 90 0
      3rdparty/spirv-tools/source/opt/fix_func_call_arguments.cpp
  11. 47 0
      3rdparty/spirv-tools/source/opt/fix_func_call_arguments.h
  12. 59 0
      3rdparty/spirv-tools/source/opt/folding_rules.cpp
  13. 2 0
      3rdparty/spirv-tools/source/opt/if_conversion.cpp
  14. 9 0
      3rdparty/spirv-tools/source/opt/ir_builder.h
  15. 13 0
      3rdparty/spirv-tools/source/opt/ir_context.cpp
  16. 4 0
      3rdparty/spirv-tools/source/opt/ir_context.h
  17. 4 0
      3rdparty/spirv-tools/source/opt/loop_descriptor.cpp
  18. 2 1
      3rdparty/spirv-tools/source/opt/loop_descriptor.h
  19. 7 0
      3rdparty/spirv-tools/source/opt/optimizer.cpp
  20. 1 0
      3rdparty/spirv-tools/source/opt/passes.h
  21. 25 45
      3rdparty/spirv-tools/source/opt/spread_volatile_semantics.cpp
  22. 6 7
      3rdparty/spirv-tools/source/opt/spread_volatile_semantics.h
  23. 6 2
      3rdparty/spirv-tools/source/val/validate_builtins.cpp
  24. 55 0
      3rdparty/spirv-tools/source/val/validate_non_uniform.cpp
  25. 7 1
      3rdparty/spirv-tools/source/val/validation_state.cpp

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

@@ -1 +1 @@
-"v2022.2-dev", "SPIRV-Tools v2022.2-dev 5ae22716672dc8dbefc3b24f142ffa9f50bab74c"
+"v2022.3-dev", "SPIRV-Tools v2022.3-dev 560669f6c0e19daf8f29e1f085599f0765e4ee35"

+ 2 - 0
3rdparty/spirv-tools/include/generated/core.insts-unified1.inc

@@ -28,6 +28,7 @@ static const SpvCapability pygen_variable_caps_GroupNonUniformArithmeticGroupNon
 static const SpvCapability pygen_variable_caps_GroupNonUniformBallot[] = {SpvCapabilityGroupNonUniformBallot};
 static const SpvCapability pygen_variable_caps_GroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformPartitionedNV};
 static const SpvCapability pygen_variable_caps_GroupNonUniformQuad[] = {SpvCapabilityGroupNonUniformQuad};
+static const SpvCapability pygen_variable_caps_GroupNonUniformRotateKHR[] = {SpvCapabilityGroupNonUniformRotateKHR};
 static const SpvCapability pygen_variable_caps_GroupNonUniformShuffle[] = {SpvCapabilityGroupNonUniformShuffle};
 static const SpvCapability pygen_variable_caps_GroupNonUniformShuffleRelative[] = {SpvCapabilityGroupNonUniformShuffleRelative};
 static const SpvCapability pygen_variable_caps_GroupNonUniformVote[] = {SpvCapabilityGroupNonUniformVote};
@@ -454,6 +455,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"SubgroupAllKHR", SpvOpSubgroupAllKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu, 0xffffffffu},
   {"SubgroupAnyKHR", SpvOpSubgroupAnyKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu, 0xffffffffu},
   {"SubgroupAllEqualKHR", SpvOpSubgroupAllEqualKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu, 0xffffffffu},
+  {"GroupNonUniformRotateKHR", SpvOpGroupNonUniformRotateKHR, 1, pygen_variable_caps_GroupNonUniformRotateKHR, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"SubgroupReadInvocationKHR", SpvOpSubgroupReadInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu, 0xffffffffu},
   {"TraceRayKHR", SpvOpTraceRayKHR, 1, pygen_variable_caps_RayTracingKHR, 11, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu},
   {"ExecuteCallableKHR", SpvOpExecuteCallableKHR, 1, pygen_variable_caps_RayTracingKHR, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu},

File diff suppressed because it is too large
+ 4 - 0
3rdparty/spirv-tools/include/generated/enum_string_mapping.inc


+ 2 - 0
3rdparty/spirv-tools/include/generated/extension_enum.inc

@@ -68,6 +68,7 @@ kSPV_KHR_no_integer_wrap_decoration,
 kSPV_KHR_non_semantic_info,
 kSPV_KHR_physical_storage_buffer,
 kSPV_KHR_post_depth_coverage,
+kSPV_KHR_ray_cull_mask,
 kSPV_KHR_ray_query,
 kSPV_KHR_ray_tracing,
 kSPV_KHR_shader_atomic_counter_ops,
@@ -75,6 +76,7 @@ kSPV_KHR_shader_ballot,
 kSPV_KHR_shader_clock,
 kSPV_KHR_shader_draw_parameters,
 kSPV_KHR_storage_buffer_storage_class,
+kSPV_KHR_subgroup_rotate,
 kSPV_KHR_subgroup_uniform_control_flow,
 kSPV_KHR_subgroup_vote,
 kSPV_KHR_terminate_invocation,

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

@@ -31,4 +31,5 @@
 {30, "SpvGenTwo community", "SpvGenTwo SPIR-V IR Tools", "SpvGenTwo community SpvGenTwo SPIR-V IR Tools"},
 {31, "Google", "Skia SkSL", "Google Skia SkSL"},
 {32, "TornadoVM", "SPIRV Beehive Toolkit", "TornadoVM SPIRV Beehive Toolkit"},
-{33, "DragonJoker", "ShaderWriter", "DragonJoker ShaderWriter"},
+{33, "DragonJoker", "ShaderWriter", "DragonJoker ShaderWriter"},
+{34, "Rayan Hatout", "SPIRVSmith", "Rayan Hatout SPIRVSmith"},

+ 11 - 3
3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc

@@ -70,6 +70,7 @@ static const SpvCapability pygen_variable_caps_OptNoneINTEL[] = {SpvCapabilityOp
 static const SpvCapability pygen_variable_caps_PerViewAttributesNVMeshShadingNV[] = {SpvCapabilityPerViewAttributesNV, SpvCapabilityMeshShadingNV};
 static const SpvCapability pygen_variable_caps_PhysicalStorageBufferAddresses[] = {SpvCapabilityPhysicalStorageBufferAddresses};
 static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes};
+static const SpvCapability pygen_variable_caps_RayCullMaskKHR[] = {SpvCapabilityRayCullMaskKHR};
 static const SpvCapability pygen_variable_caps_RayQueryKHR[] = {SpvCapabilityRayQueryKHR};
 static const SpvCapability pygen_variable_caps_RayQueryKHRRayTracingKHR[] = {SpvCapabilityRayQueryKHR, SpvCapabilityRayTracingKHR};
 static const SpvCapability pygen_variable_caps_RayTracingKHR[] = {SpvCapabilityRayTracingKHR};
@@ -183,6 +184,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_linkonce_odr[] = {s
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_multiview[] = {spvtools::Extension::kSPV_KHR_multiview};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_no_integer_wrap_decoration[] = {spvtools::Extension::kSPV_KHR_no_integer_wrap_decoration};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_post_depth_coverage[] = {spvtools::Extension::kSPV_KHR_post_depth_coverage};
+static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_cull_mask[] = {spvtools::Extension::kSPV_KHR_ray_cull_mask};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_query};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_querySPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_query, spvtools::Extension::kSPV_KHR_ray_tracing};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing};
@@ -193,6 +195,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {s
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_draw_parameters[] = {spvtools::Extension::kSPV_KHR_shader_draw_parameters};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_draw_parametersSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_KHR_shader_draw_parameters, spvtools::Extension::kSPV_NV_mesh_shader};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_storage_buffer_storage_classSPV_KHR_variable_pointers[] = {spvtools::Extension::kSPV_KHR_storage_buffer_storage_class, spvtools::Extension::kSPV_KHR_variable_pointers};
+static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_rotate[] = {spvtools::Extension::kSPV_KHR_subgroup_rotate};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_uniform_control_flow[] = {spvtools::Extension::kSPV_KHR_subgroup_uniform_control_flow};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_vote[] = {spvtools::Extension::kSPV_KHR_subgroup_vote};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_uniform_group_instructions[] = {spvtools::Extension::kSPV_KHR_uniform_group_instructions};
@@ -357,7 +360,8 @@ static const spv_operand_desc_t pygen_variable_SourceLanguageEntries[] = {
   {"OpenCL_C", 3, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"OpenCL_CPP", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"HLSL", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
-  {"CPP_for_OpenCL", 6, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
+  {"CPP_for_OpenCL", 6, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
+  {"SYCL", 7, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_ExecutionModelEntries[] = {
@@ -467,7 +471,8 @@ static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = {
   {"MaxWorkDimINTEL", 5894, 1, pygen_variable_caps_KernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
   {"NoGlobalOffsetINTEL", 5895, 1, pygen_variable_caps_KernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {}, 0xffffffffu, 0xffffffffu},
   {"NumSIMDWorkitemsINTEL", 5896, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
-  {"SchedulerTargetFmaxMhzINTEL", 5903, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
+  {"SchedulerTargetFmaxMhzINTEL", 5903, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"NamedBarrierCountINTEL", 6417, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = {
@@ -907,7 +912,8 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
   {"WarpsPerSMNV", 5374, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu},
   {"SMCountNV", 5375, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu},
   {"WarpIDNV", 5376, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu},
-  {"SMIDNV", 5377, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu}
+  {"SMIDNV", 5377, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu},
+  {"CullMaskKHR", 6021, 1, pygen_variable_caps_RayCullMaskKHR, 1, pygen_variable_exts_SPV_KHR_ray_cull_mask, {}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_ScopeEntries[] = {
@@ -1151,7 +1157,9 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"DotProductInput4x8BitPackedKHR", 6018, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
   {"DotProduct", 6019, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
   {"DotProductKHR", 6019, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
+  {"RayCullMaskKHR", 6020, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_ray_cull_mask, {}, 0xffffffffu, 0xffffffffu},
   {"BitInstructions", 6025, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_bit_instructions, {}, 0xffffffffu, 0xffffffffu},
+  {"GroupNonUniformRotateKHR", 6026, 1, pygen_variable_caps_GroupNonUniform, 1, pygen_variable_exts_SPV_KHR_subgroup_rotate, {}, 0xffffffffu, 0xffffffffu},
   {"AtomicFloat32AddEXT", 6033, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
   {"AtomicFloat64AddEXT", 6034, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
   {"LongConstantCompositeINTEL", 6089, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_long_constant_composite, {}, 0xffffffffu, 0xffffffffu},

+ 5 - 0
3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp

@@ -907,6 +907,11 @@ Optimizer::PassToken CreateConvertToSampledImagePass(
 // from every function in the module.  This is useful if you want the inliner to
 // inline these functions some reason.
 Optimizer::PassToken CreateRemoveDontInlinePass();
+// Create a fix-func-call-param pass to fix non memory argument for the function
+// call, as spirv-validation requires function parameters to be an memory
+// object, currently the pass would remove accesschain pointer argument passed
+// to the function
+Optimizer::PassToken CreateFixFuncCallArgumentsPass();
 }  // namespace spvtools
 
 #endif  // INCLUDE_SPIRV_TOOLS_OPTIMIZER_HPP_

+ 8 - 2
3rdparty/spirv-tools/source/link/linker.cpp

@@ -34,6 +34,7 @@
 #include "source/opt/ir_loader.h"
 #include "source/opt/pass_manager.h"
 #include "source/opt/remove_duplicates_pass.h"
+#include "source/opt/remove_unused_interface_variables_pass.h"
 #include "source/opt/type_manager.h"
 #include "source/spirv_constant.h"
 #include "source/spirv_target_env.h"
@@ -807,11 +808,16 @@ spv_result_t Link(const Context& context, const uint32_t* const* binaries,
   pass_res = manager.Run(&linked_context);
   if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
 
-  // Phase 11: Warn if SPIR-V limits were exceeded
+  // Phase 11: Recompute EntryPoint variables
+  manager.AddPass<opt::RemoveUnusedInterfaceVariablesPass>();
+  pass_res = manager.Run(&linked_context);
+  if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
+
+  // Phase 12: Warn if SPIR-V limits were exceeded
   res = VerifyLimits(consumer, linked_context);
   if (res != SPV_SUCCESS) return res;
 
-  // Phase 12: Output the module
+  // Phase 13: Output the module
   linked_context.module()->ToBinary(linked_binary, true);
 
   return SPV_SUCCESS;

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

@@ -528,6 +528,7 @@ bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode) {
     case SpvOpGroupNonUniformLogicalXor:
     case SpvOpGroupNonUniformQuadBroadcast:
     case SpvOpGroupNonUniformQuadSwap:
+    case SpvOpGroupNonUniformRotateKHR:
       return true;
     default:
       return false;

+ 90 - 0
3rdparty/spirv-tools/source/opt/fix_func_call_arguments.cpp

@@ -0,0 +1,90 @@
+// Copyright (c) 2022 Advanced Micro Devices, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "fix_func_call_arguments.h"
+
+#include "ir_builder.h"
+
+using namespace spvtools;
+using namespace opt;
+
+bool FixFuncCallArgumentsPass::ModuleHasASingleFunction() {
+  auto funcsNum = get_module()->end() - get_module()->begin();
+  return funcsNum == 1;
+}
+
+Pass::Status FixFuncCallArgumentsPass::Process() {
+  bool modified = false;
+  if (ModuleHasASingleFunction()) return Status::SuccessWithoutChange;
+  for (auto& func : *get_module()) {
+    func.ForEachInst([this, &modified](Instruction* inst) {
+      if (inst->opcode() == SpvOpFunctionCall) {
+        modified |= FixFuncCallArguments(inst);
+      }
+    });
+  }
+  return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
+}
+
+bool FixFuncCallArgumentsPass::FixFuncCallArguments(
+    Instruction* func_call_inst) {
+  bool modified = false;
+  for (uint32_t i = 0; i < func_call_inst->NumInOperands(); ++i) {
+    Operand& op = func_call_inst->GetInOperand(i);
+    if (op.type != SPV_OPERAND_TYPE_ID) continue;
+    Instruction* operand_inst = get_def_use_mgr()->GetDef(op.AsId());
+    if (operand_inst->opcode() == SpvOpAccessChain) {
+      uint32_t var_id =
+          ReplaceAccessChainFuncCallArguments(func_call_inst, operand_inst);
+      func_call_inst->SetInOperand(i, {var_id});
+      modified = true;
+    }
+  }
+  if (modified) {
+    context()->UpdateDefUse(func_call_inst);
+  }
+  return modified;
+}
+
+uint32_t FixFuncCallArgumentsPass::ReplaceAccessChainFuncCallArguments(
+    Instruction* func_call_inst, Instruction* operand_inst) {
+  InstructionBuilder builder(
+      context(), func_call_inst,
+      IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
+
+  Instruction* next_insert_point = func_call_inst->NextNode();
+  // Get Variable insertion point
+  Function* func = context()->get_instr_block(func_call_inst)->GetParent();
+  Instruction* variable_insertion_point = &*(func->begin()->begin());
+  Instruction* op_ptr_type = get_def_use_mgr()->GetDef(operand_inst->type_id());
+  Instruction* op_type =
+      get_def_use_mgr()->GetDef(op_ptr_type->GetSingleWordInOperand(1));
+  uint32_t varType = context()->get_type_mgr()->FindPointerToType(
+      op_type->result_id(), SpvStorageClassFunction);
+  // Create new variable
+  builder.SetInsertPoint(variable_insertion_point);
+  Instruction* var = builder.AddVariable(varType, SpvStorageClassFunction);
+  // Load access chain to the new variable before function call
+  builder.SetInsertPoint(func_call_inst);
+
+  uint32_t operand_id = operand_inst->result_id();
+  Instruction* load = builder.AddLoad(op_type->result_id(), operand_id);
+  builder.AddStore(var->result_id(), load->result_id());
+  // Load return value to the acesschain after function call
+  builder.SetInsertPoint(next_insert_point);
+  load = builder.AddLoad(op_type->result_id(), var->result_id());
+  builder.AddStore(operand_id, load->result_id());
+
+  return var->result_id();
+}

+ 47 - 0
3rdparty/spirv-tools/source/opt/fix_func_call_arguments.h

@@ -0,0 +1,47 @@
+// Copyright (c) 2022 Advanced Micro Devices, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _VAR_FUNC_CALL_PASS_H
+#define _VAR_FUNC_CALL_PASS_H
+
+#include "source/opt/pass.h"
+
+namespace spvtools {
+namespace opt {
+class FixFuncCallArgumentsPass : public Pass {
+ public:
+  FixFuncCallArgumentsPass() {}
+  const char* name() const override { return "fix-for-funcall-param"; }
+  Status Process() override;
+  // Returns true if the module has one one function.
+  bool ModuleHasASingleFunction();
+  // Copies from the memory pointed to by |operand_inst| to a new function scope
+  // variable created before |func_call_inst|, and
+  // copies the value of the new variable back to the memory pointed to by
+  // |operand_inst| after |funct_call_inst|  Returns the id of
+  // the new variable.
+  uint32_t ReplaceAccessChainFuncCallArguments(Instruction* func_call_inst,
+                                               Instruction* operand_inst);
+
+  // Fix function call |func_call_inst| non memory object arguments
+  bool FixFuncCallArguments(Instruction* func_call_inst);
+
+  IRContext::Analysis GetPreservedAnalyses() override {
+    return IRContext::kAnalysisTypes;
+  }
+};
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // _VAR_FUNC_CALL_PASS_H

+ 59 - 0
3rdparty/spirv-tools/source/opt/folding_rules.cpp

@@ -1430,6 +1430,64 @@ FoldingRule FactorAddMuls() {
   };
 }
 
+// Replaces |inst| inplace with an FMA instruction |(x*y)+a|.
+void ReplaceWithFma(Instruction* inst, uint32_t x, uint32_t y, uint32_t a) {
+  uint32_t ext =
+      inst->context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
+
+  if (ext == 0) {
+    inst->context()->AddExtInstImport("GLSL.std.450");
+    ext = inst->context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
+    assert(ext != 0 &&
+           "Could not add the GLSL.std.450 extended instruction set");
+  }
+
+  std::vector<Operand> operands;
+  operands.push_back({SPV_OPERAND_TYPE_ID, {ext}});
+  operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {GLSLstd450Fma}});
+  operands.push_back({SPV_OPERAND_TYPE_ID, {x}});
+  operands.push_back({SPV_OPERAND_TYPE_ID, {y}});
+  operands.push_back({SPV_OPERAND_TYPE_ID, {a}});
+
+  inst->SetOpcode(SpvOpExtInst);
+  inst->SetInOperands(std::move(operands));
+}
+
+// Folds a multiple and add into an Fma.
+//
+// Cases:
+// (x * y) + a = Fma x y a
+// a + (x * y) = Fma x y a
+bool MergeMulAddArithmetic(IRContext* context, Instruction* inst,
+                           const std::vector<const analysis::Constant*>&) {
+  assert(inst->opcode() == SpvOpFAdd);
+
+  if (!inst->IsFloatingPointFoldingAllowed()) {
+    return false;
+  }
+
+  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
+  for (int i = 0; i < 2; i++) {
+    uint32_t op_id = inst->GetSingleWordInOperand(i);
+    Instruction* op_inst = def_use_mgr->GetDef(op_id);
+
+    if (op_inst->opcode() != SpvOpFMul) {
+      continue;
+    }
+
+    if (!op_inst->IsFloatingPointFoldingAllowed()) {
+      continue;
+    }
+
+    uint32_t x = op_inst->GetSingleWordInOperand(0);
+    uint32_t y = op_inst->GetSingleWordInOperand(1);
+    uint32_t a = inst->GetSingleWordInOperand((i + 1) % 2);
+    ReplaceWithFma(inst, x, y, a);
+    return true;
+  }
+  return false;
+}
+
 FoldingRule IntMultipleBy1() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
@@ -2543,6 +2601,7 @@ void FoldingRules::AddFoldingRules() {
   rules_[SpvOpFAdd].push_back(MergeAddSubArithmetic());
   rules_[SpvOpFAdd].push_back(MergeGenericAddSubArithmetic());
   rules_[SpvOpFAdd].push_back(FactorAddMuls());
+  rules_[SpvOpFAdd].push_back(MergeMulAddArithmetic);
 
   rules_[SpvOpFDiv].push_back(RedundantFDiv());
   rules_[SpvOpFDiv].push_back(ReciprocalFDiv());

+ 2 - 0
3rdparty/spirv-tools/source/opt/if_conversion.cpp

@@ -169,6 +169,8 @@ bool IfConversion::CheckBlock(BasicBlock* block, DominatorAnalysis* dominators,
   if (branch->opcode() != SpvOpBranchConditional) return false;
   auto merge = (*common)->GetMergeInst();
   if (!merge || merge->opcode() != SpvOpSelectionMerge) return false;
+  if (merge->GetSingleWordInOperand(1) == SpvSelectionControlDontFlattenMask)
+    return false;
   if ((*common)->MergeBlockIdIfAny() != block->id()) return false;
 
   return true;

+ 9 - 0
3rdparty/spirv-tools/source/opt/ir_builder.h

@@ -487,6 +487,15 @@ class InstructionBuilder {
     return AddInstruction(std::move(new_inst));
   }
 
+  Instruction* AddVariable(uint32_t type_id, uint32_t storage_class) {
+    std::vector<Operand> operands;
+    operands.push_back({SPV_OPERAND_TYPE_ID, {storage_class}});
+    std::unique_ptr<Instruction> new_inst(
+        new Instruction(GetContext(), SpvOpVariable, type_id,
+                        GetContext()->TakeNextId(), operands));
+    return AddInstruction(std::move(new_inst));
+  }
+
   Instruction* AddStore(uint32_t ptr_id, uint32_t obj_id) {
     std::vector<Operand> operands;
     operands.push_back({SPV_OPERAND_TYPE_ID, {ptr_id}});

+ 13 - 0
3rdparty/spirv-tools/source/opt/ir_context.cpp

@@ -926,6 +926,19 @@ bool IRContext::ProcessCallTreeFromRoots(ProcessFunction& pfn,
   return modified;
 }
 
+void IRContext::CollectCallTreeFromRoots(unsigned entryId,
+                                         std::unordered_set<uint32_t>* funcs) {
+  std::queue<uint32_t> roots;
+  roots.push(entryId);
+  while (!roots.empty()) {
+    const uint32_t fi = roots.front();
+    roots.pop();
+    funcs->insert(fi);
+    Function* fn = GetFunction(fi);
+    AddCalls(fn, &roots);
+  }
+}
+
 void IRContext::EmitErrorMessage(std::string message, Instruction* inst) {
   if (!consumer()) {
     return;

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

@@ -411,6 +411,10 @@ class IRContext {
   void CollectNonSemanticTree(Instruction* inst,
                               std::unordered_set<Instruction*>* to_kill);
 
+  // Collect function reachable from |entryId|, returns |funcs|
+  void CollectCallTreeFromRoots(unsigned entryId,
+                                std::unordered_set<uint32_t>* funcs);
+
   // Returns true if all of the given analyses are valid.
   bool AreAnalysesValid(Analysis set) { return (set & valid_analyses_) == set; }
 

+ 4 - 0
3rdparty/spirv-tools/source/opt/loop_descriptor.cpp

@@ -754,6 +754,10 @@ bool Loop::FindNumberOfIterations(const Instruction* induction,
 // |step_value| is NOT cleanly divisible then we add one to the sum.
 int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value,
                             int64_t init_value, int64_t step_value) const {
+  if (step_value == 0) {
+    return 0;
+  }
+
   int64_t diff = 0;
 
   switch (condition) {

+ 2 - 1
3rdparty/spirv-tools/source/opt/loop_descriptor.h

@@ -398,7 +398,8 @@ class Loop {
   // Each different loop |condition| affects how we calculate the number of
   // iterations using the |condition_value|, |init_value|, and |step_values| of
   // the induction variable. This method will return the number of iterations in
-  // a loop with those values for a given |condition|.
+  // a loop with those values for a given |condition|.  Returns 0 if the number
+  // of iterations could not be computed.
   int64_t GetIterations(SpvOp condition, int64_t condition_value,
                         int64_t init_value, int64_t step_value) const;
 

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

@@ -525,6 +525,8 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
     RegisterPass(CreateRemoveDontInlinePass());
   } else if (pass_name == "eliminate-dead-input-components") {
     RegisterPass(CreateEliminateDeadInputComponentsPass());
+  } else if (pass_name == "fix-func-call-param") {
+    RegisterPass(CreateFixFuncCallArgumentsPass());
   } else if (pass_name == "convert-to-sampled-image") {
     if (pass_args.size() > 0) {
       auto descriptor_set_binding_pairs =
@@ -1022,4 +1024,9 @@ Optimizer::PassToken CreateRemoveDontInlinePass() {
   return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::RemoveDontInline>());
 }
+
+Optimizer::PassToken CreateFixFuncCallArgumentsPass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::FixFuncCallArgumentsPass>());
+}
 }  // namespace spvtools

+ 1 - 0
3rdparty/spirv-tools/source/opt/passes.h

@@ -37,6 +37,7 @@
 #include "source/opt/eliminate_dead_input_components_pass.h"
 #include "source/opt/eliminate_dead_members_pass.h"
 #include "source/opt/empty_pass.h"
+#include "source/opt/fix_func_call_arguments.h"
 #include "source/opt/fix_storage_class.h"
 #include "source/opt/flatten_decoration_pass.h"
 #include "source/opt/fold_spec_constant_op_and_composite_pass.h"

+ 25 - 45
3rdparty/spirv-tools/source/opt/spread_volatile_semantics.cpp

@@ -68,38 +68,12 @@ bool HasVolatileDecoration(analysis::DecorationManager* decoration_manager,
   return decoration_manager->HasDecoration(var_id, SpvDecorationVolatile);
 }
 
-bool HasOnlyEntryPointsAsFunctions(IRContext* context, Module* module) {
-  std::unordered_set<uint32_t> entry_function_ids;
-  for (Instruction& entry_point : module->entry_points()) {
-    entry_function_ids.insert(
-        entry_point.GetSingleWordInOperand(kOpEntryPointInOperandEntryPoint));
-  }
-  for (auto& function : *module) {
-    if (entry_function_ids.find(function.result_id()) ==
-        entry_function_ids.end()) {
-      std::string message(
-          "Functions of SPIR-V for spread-volatile-semantics pass input must "
-          "be inlined except entry points");
-      message += "\n  " + function.DefInst().PrettyPrint(
-                              SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
-      context->consumer()(SPV_MSG_ERROR, "", {0, 0, 0}, message.c_str());
-      return false;
-    }
-  }
-  return true;
-}
-
 }  // namespace
 
 Pass::Status SpreadVolatileSemantics::Process() {
   if (HasNoExecutionModel()) {
     return Status::SuccessWithoutChange;
   }
-
-  if (!HasOnlyEntryPointsAsFunctions(context(), get_module())) {
-    return Status::Failure;
-  }
-
   const bool is_vk_memory_model_enabled =
       context()->get_feature_mgr()->HasCapability(
           SpvCapabilityVulkanMemoryModel);
@@ -142,6 +116,8 @@ bool SpreadVolatileSemantics::IsTargetUsedByNonVolatileLoadInEntryPoint(
     uint32_t var_id, Instruction* entry_point) {
   uint32_t entry_function_id =
       entry_point->GetSingleWordInOperand(kOpEntryPointInOperandEntryPoint);
+  std::unordered_set<uint32_t> funcs;
+  context()->CollectCallTreeFromRoots(entry_function_id, &funcs);
   return !VisitLoadsOfPointersToVariableInEntries(
       var_id,
       [](Instruction* load) {
@@ -154,7 +130,7 @@ bool SpreadVolatileSemantics::IsTargetUsedByNonVolatileLoadInEntryPoint(
             load->GetSingleWordInOperand(kOpLoadInOperandMemoryOperands);
         return (memory_operands & SpvMemoryAccessVolatileMask) != 0;
       },
-      {entry_function_id});
+      funcs);
 }
 
 bool SpreadVolatileSemantics::HasInterfaceInConflictOfVolatileSemantics() {
@@ -225,7 +201,7 @@ void SpreadVolatileSemantics::DecorateVarWithVolatile(Instruction* var) {
 
 bool SpreadVolatileSemantics::VisitLoadsOfPointersToVariableInEntries(
     uint32_t var_id, const std::function<bool(Instruction*)>& handle_load,
-    const std::unordered_set<uint32_t>& entry_function_ids) {
+    const std::unordered_set<uint32_t>& function_ids) {
   std::vector<uint32_t> worklist({var_id});
   auto* def_use_mgr = context()->get_def_use_mgr();
   while (!worklist.empty()) {
@@ -233,11 +209,11 @@ bool SpreadVolatileSemantics::VisitLoadsOfPointersToVariableInEntries(
     worklist.pop_back();
     bool finish_traversal = !def_use_mgr->WhileEachUser(
         ptr_id, [this, &worklist, &ptr_id, handle_load,
-                 &entry_function_ids](Instruction* user) {
+                 &function_ids](Instruction* user) {
           BasicBlock* block = context()->get_instr_block(user);
           if (block == nullptr ||
-              entry_function_ids.find(block->GetParent()->result_id()) ==
-                  entry_function_ids.end()) {
+              function_ids.find(block->GetParent()->result_id()) ==
+                  function_ids.end()) {
             return true;
           }
 
@@ -266,21 +242,25 @@ void SpreadVolatileSemantics::SetVolatileForLoadsInEntries(
     Instruction* var, const std::unordered_set<uint32_t>& entry_function_ids) {
   // Set Volatile memory operand for all load instructions if they do not have
   // it.
-  VisitLoadsOfPointersToVariableInEntries(
-      var->result_id(),
-      [](Instruction* load) {
-        if (load->NumInOperands() <= kOpLoadInOperandMemoryOperands) {
-          load->AddOperand(
-              {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessVolatileMask}});
+  for (auto entry_id : entry_function_ids) {
+    std::unordered_set<uint32_t> funcs;
+    context()->CollectCallTreeFromRoots(entry_id, &funcs);
+    VisitLoadsOfPointersToVariableInEntries(
+        var->result_id(),
+        [](Instruction* load) {
+          if (load->NumInOperands() <= kOpLoadInOperandMemoryOperands) {
+            load->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
+                              {SpvMemoryAccessVolatileMask}});
+            return true;
+          }
+          uint32_t memory_operands =
+              load->GetSingleWordInOperand(kOpLoadInOperandMemoryOperands);
+          memory_operands |= SpvMemoryAccessVolatileMask;
+          load->SetInOperand(kOpLoadInOperandMemoryOperands, {memory_operands});
           return true;
-        }
-        uint32_t memory_operands =
-            load->GetSingleWordInOperand(kOpLoadInOperandMemoryOperands);
-        memory_operands |= SpvMemoryAccessVolatileMask;
-        load->SetInOperand(kOpLoadInOperandMemoryOperands, {memory_operands});
-        return true;
-      },
-      entry_function_ids);
+        },
+        funcs);
+  }
 }
 
 bool SpreadVolatileSemantics::IsTargetForVolatileSemantics(

+ 6 - 7
3rdparty/spirv-tools/source/opt/spread_volatile_semantics.h

@@ -72,15 +72,14 @@ class SpreadVolatileSemantics : public Pass {
                                                  Instruction* entry_point);
 
   // Visits load instructions of pointers to variable whose result id is
-  // |var_id| if the load instructions are in entry points whose
-  // function id is one of |entry_function_ids|. |handle_load| is a function to
-  // do some actions for the load instructions. Finishes the traversal and
-  // returns false if |handle_load| returns false for a load instruction.
-  // Otherwise, returns true after running |handle_load| for all the load
-  // instructions.
+  // |var_id| if the load instructions are in reachable functions from entry
+  // points. |handle_load| is a function to do some actions for the load
+  // instructions. Finishes the traversal and returns false if |handle_load|
+  // returns false for a load instruction. Otherwise, returns true after running
+  // |handle_load| for all the load instructions.
   bool VisitLoadsOfPointersToVariableInEntries(
       uint32_t var_id, const std::function<bool(Instruction*)>& handle_load,
-      const std::unordered_set<uint32_t>& entry_function_ids);
+      const std::unordered_set<uint32_t>& function_ids);
 
   // Sets Memory Operands of OpLoad instructions that load |var| or pointers
   // of |var| as Volatile if the function id of the OpLoad instruction is

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

@@ -120,7 +120,7 @@ typedef enum VUIDError_ {
   VUIDErrorMax,
 } VUIDError;
 
-const static uint32_t NumVUIDBuiltins = 33;
+const static uint32_t NumVUIDBuiltins = 34;
 
 typedef struct {
   SpvBuiltIn builtIn;
@@ -162,6 +162,7 @@ std::array<BuiltinVUIDMapping, NumVUIDBuiltins> builtinVUIDInfo = {{
     {SpvBuiltInFragSizeEXT,               {4220, 4221, 4222}},
     {SpvBuiltInFragStencilRefEXT,         {4223, 4224, 4225}},
     {SpvBuiltInFullyCoveredEXT,           {4232, 4233, 4234}},
+    {SpvBuiltInCullMaskKHR,               {6735, 6736, 6737}},
     // clang-format off
 } };
 
@@ -208,6 +209,7 @@ bool IsExecutionModelValidForRtBuiltIn(SpvBuiltIn builtin,
     case SpvBuiltInRayTmaxKHR:
     case SpvBuiltInWorldRayDirectionKHR:
     case SpvBuiltInWorldRayOriginKHR:
+    case SpvBuiltInCullMaskKHR:
       switch (stage) {
         case SpvExecutionModelIntersectionKHR:
         case SpvExecutionModelAnyHitKHR:
@@ -3851,6 +3853,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
       case SpvBuiltInInstanceId:
       case SpvBuiltInRayGeometryIndexKHR:
       case SpvBuiltInIncomingRayFlagsKHR:
+      case SpvBuiltInCullMaskKHR:
         // i32 scalar
         if (spv_result_t error = ValidateI32(
                 decoration, inst,
@@ -4151,7 +4154,8 @@ spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
     case SpvBuiltInObjectToWorldKHR:        // alias SpvBuiltInObjectToWorldNV
     case SpvBuiltInWorldToObjectKHR:        // alias SpvBuiltInWorldToObjectNV
     case SpvBuiltInIncomingRayFlagsKHR:    // alias SpvBuiltInIncomingRayFlagsNV
-    case SpvBuiltInRayGeometryIndexKHR: {  // NOT present in NV
+    case SpvBuiltInRayGeometryIndexKHR:    // NOT present in NV
+    case SpvBuiltInCullMaskKHR: {
       return ValidateRayTracingBuiltinsAtDefinition(decoration, inst);
     }
     case SpvBuiltInWorkDim:

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

@@ -63,6 +63,59 @@ spv_result_t ValidateGroupNonUniformBallotBitCount(ValidationState_t& _,
   return SPV_SUCCESS;
 }
 
+spv_result_t ValidateGroupNonUniformRotateKHR(ValidationState_t& _,
+                                              const Instruction* inst) {
+  // Scope is already checked by ValidateExecutionScope() above.
+  const uint32_t result_type = inst->type_id();
+  if (!_.IsIntScalarOrVectorType(result_type) &&
+      !_.IsFloatScalarOrVectorType(result_type) &&
+      !_.IsBoolScalarOrVectorType(result_type)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Expected Result Type to be a scalar or vector of "
+              "floating-point, integer or boolean type.";
+  }
+
+  const uint32_t value_type = _.GetTypeId(inst->GetOperandAs<uint32_t>(3));
+  if (value_type != result_type) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Result Type must be the same as the type of Value.";
+  }
+
+  const uint32_t delta_type = _.GetTypeId(inst->GetOperandAs<uint32_t>(4));
+  if (!_.IsUnsignedIntScalarType(delta_type)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Delta must be a scalar of integer type, whose Signedness "
+              "operand is 0.";
+  }
+
+  if (inst->words().size() > 6) {
+    const uint32_t cluster_size_op_id = inst->GetOperandAs<uint32_t>(5);
+    const uint32_t cluster_size_type = _.GetTypeId(cluster_size_op_id);
+    if (!_.IsUnsignedIntScalarType(cluster_size_type)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "ClusterSize must be a scalar of integer type, whose "
+                "Signedness operand is 0.";
+    }
+
+    uint64_t cluster_size;
+    if (!_.GetConstantValUint64(cluster_size_op_id, &cluster_size)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "ClusterSize must come from a constant instruction.";
+    }
+
+    if ((cluster_size == 0) || ((cluster_size & (cluster_size - 1)) != 0)) {
+      return _.diag(SPV_WARNING, inst)
+             << "Behavior is undefined unless ClusterSize is at least 1 and a "
+                "power of 2.";
+    }
+
+    // TODO(kpet) Warn about undefined behavior when ClusterSize is greater than
+    // the declared SubGroupSize
+  }
+
+  return SPV_SUCCESS;
+}
+
 }  // namespace
 
 // Validates correctness of non-uniform group instructions.
@@ -79,6 +132,8 @@ spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst) {
   switch (opcode) {
     case SpvOpGroupNonUniformBallotBitCount:
       return ValidateGroupNonUniformBallotBitCount(_, inst);
+    case SpvOpGroupNonUniformRotateKHR:
+      return ValidateGroupNonUniformRotateKHR(_, inst);
     default:
       break;
   }

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

@@ -1443,6 +1443,12 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
       return VUID_WRAP(VUID-CullDistance-CullDistance-04199);
     case 4200:
       return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
+    case 6735:
+      return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06735); // Execution Model
+    case 6736:
+      return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06736); // input storage
+    case 6737:
+      return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06737); // 32 int scalar
     case 4205:
       return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04205);
     case 4206:
@@ -1926,4 +1932,4 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
 }
 
 }  // namespace val
-}  // namespace spvtools
+}  // namespace spvtools

Some files were not shown because too many files changed in this diff