فهرست منبع

Updated spirv-tools.

Бранимир Караџић 6 سال پیش
والد
کامیت
b28dfbd770
27فایلهای تغییر یافته به همراه1106 افزوده شده و 44 حذف شده
  1. 1 0
      3rdparty/spirv-tools/Android.mk
  2. 2 0
      3rdparty/spirv-tools/BUILD.gn
  3. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  4. 17 17
      3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
  5. 7 0
      3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp
  6. 32 0
      3rdparty/spirv-tools/source/opcode.cpp
  7. 4 0
      3rdparty/spirv-tools/source/opcode.h
  8. 2 0
      3rdparty/spirv-tools/source/opt/CMakeLists.txt
  9. 1 0
      3rdparty/spirv-tools/source/opt/ccp_pass.cpp
  10. 33 0
      3rdparty/spirv-tools/source/opt/folding_rules.cpp
  11. 10 1
      3rdparty/spirv-tools/source/opt/optimizer.cpp
  12. 1 0
      3rdparty/spirv-tools/source/opt/passes.h
  13. 57 0
      3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp
  14. 51 0
      3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h
  15. 17 2
      3rdparty/spirv-tools/source/val/validate_function.cpp
  16. 30 0
      3rdparty/spirv-tools/source/val/validate_instruction.cpp
  17. 16 0
      3rdparty/spirv-tools/source/val/validate_mode_setting.cpp
  18. 1 0
      3rdparty/spirv-tools/test/opt/CMakeLists.txt
  19. 29 0
      3rdparty/spirv-tools/test/opt/ccp_test.cpp
  20. 100 0
      3rdparty/spirv-tools/test/opt/fold_test.cpp
  21. 96 6
      3rdparty/spirv-tools/test/opt/optimizer_test.cpp
  22. 406 0
      3rdparty/spirv-tools/test/opt/strip_atomic_counter_memory_test.cpp
  23. 2 0
      3rdparty/spirv-tools/test/val/val_decoration_test.cpp
  24. 12 10
      3rdparty/spirv-tools/test/val/val_function_test.cpp
  25. 48 7
      3rdparty/spirv-tools/test/val/val_modes_test.cpp
  26. 128 0
      3rdparty/spirv-tools/test/val/val_storage_test.cpp
  27. 2 0
      3rdparty/spirv-tools/tools/opt/opt.cpp

+ 1 - 0
3rdparty/spirv-tools/Android.mk

@@ -154,6 +154,7 @@ SPVTOOLS_OPT_SRC_FILES := \
 		source/opt/simplification_pass.cpp \
 		source/opt/ssa_rewrite_pass.cpp \
 		source/opt/strength_reduction_pass.cpp \
+		source/opt/strip_atomic_counter_memory_pass.cpp \
 		source/opt/strip_debug_info_pass.cpp \
 		source/opt/strip_reflect_info_pass.cpp \
 		source/opt/struct_cfg_analysis.cpp \

+ 2 - 0
3rdparty/spirv-tools/BUILD.gn

@@ -612,6 +612,8 @@ static_library("spvtools_opt") {
     "source/opt/ssa_rewrite_pass.h",
     "source/opt/strength_reduction_pass.cpp",
     "source/opt/strength_reduction_pass.h",
+    "source/opt/strip_atomic_counter_memory_pass.cpp",
+    "source/opt/strip_atomic_counter_memory_pass.h",
     "source/opt/strip_debug_info_pass.cpp",
     "source/opt/strip_debug_info_pass.h",
     "source/opt/strip_reflect_info_pass.cpp",

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

@@ -1 +1 @@
-"v2019.2", "SPIRV-Tools v2019.2 79f67a4905acf223f9e37a52e059a62c2bdbdc69"
+"v2019.2", "SPIRV-Tools v2019.2 45a64efab9d50ebcf9694a3297acc3223502610d"

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

@@ -8,7 +8,7 @@ static const SpvCapability pygen_variable_caps_FragmentMaskAMD[] = {SpvCapabilit
 static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
 static const SpvCapability pygen_variable_caps_GeometryStreams[] = {SpvCapabilityGeometryStreams};
 static const SpvCapability pygen_variable_caps_GroupNonUniform[] = {SpvCapabilityGroupNonUniform};
-static const SpvCapability pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered[] = {SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformClustered};
+static const SpvCapability pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformClustered, SpvCapabilityGroupNonUniformPartitionedNV};
 static const SpvCapability pygen_variable_caps_GroupNonUniformBallot[] = {SpvCapabilityGroupNonUniformBallot};
 static const SpvCapability pygen_variable_caps_GroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformPartitionedNV};
 static const SpvCapability pygen_variable_caps_GroupNonUniformQuad[] = {SpvCapabilityGroupNonUniformQuad};
@@ -375,22 +375,22 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"GroupNonUniformShuffleXor", SpvOpGroupNonUniformShuffleXor, 1, pygen_variable_caps_GroupNonUniformShuffle, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
   {"GroupNonUniformShuffleUp", SpvOpGroupNonUniformShuffleUp, 1, pygen_variable_caps_GroupNonUniformShuffleRelative, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
   {"GroupNonUniformShuffleDown", SpvOpGroupNonUniformShuffleDown, 1, pygen_variable_caps_GroupNonUniformShuffleRelative, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformIAdd", SpvOpGroupNonUniformIAdd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformFAdd", SpvOpGroupNonUniformFAdd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformIMul", SpvOpGroupNonUniformIMul, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformFMul", SpvOpGroupNonUniformFMul, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformSMin", SpvOpGroupNonUniformSMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformUMin", SpvOpGroupNonUniformUMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformFMin", SpvOpGroupNonUniformFMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformSMax", SpvOpGroupNonUniformSMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformUMax", SpvOpGroupNonUniformUMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformFMax", SpvOpGroupNonUniformFMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformBitwiseAnd", SpvOpGroupNonUniformBitwiseAnd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformBitwiseOr", SpvOpGroupNonUniformBitwiseOr, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformBitwiseXor", SpvOpGroupNonUniformBitwiseXor, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformLogicalAnd", SpvOpGroupNonUniformLogicalAnd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformLogicalOr", SpvOpGroupNonUniformLogicalOr, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
-  {"GroupNonUniformLogicalXor", SpvOpGroupNonUniformLogicalXor, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformIAdd", SpvOpGroupNonUniformIAdd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformFAdd", SpvOpGroupNonUniformFAdd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformIMul", SpvOpGroupNonUniformIMul, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformFMul", SpvOpGroupNonUniformFMul, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformSMin", SpvOpGroupNonUniformSMin, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformUMin", SpvOpGroupNonUniformUMin, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformFMin", SpvOpGroupNonUniformFMin, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformSMax", SpvOpGroupNonUniformSMax, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformUMax", SpvOpGroupNonUniformUMax, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformFMax", SpvOpGroupNonUniformFMax, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformBitwiseAnd", SpvOpGroupNonUniformBitwiseAnd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformBitwiseOr", SpvOpGroupNonUniformBitwiseOr, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformBitwiseXor", SpvOpGroupNonUniformBitwiseXor, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformLogicalAnd", SpvOpGroupNonUniformLogicalAnd, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformLogicalOr", SpvOpGroupNonUniformLogicalOr, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
+  {"GroupNonUniformLogicalXor", SpvOpGroupNonUniformLogicalXor, 3, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClusteredGroupNonUniformPartitionedNV, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
   {"GroupNonUniformQuadBroadcast", SpvOpGroupNonUniformQuadBroadcast, 1, pygen_variable_caps_GroupNonUniformQuad, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
   {"GroupNonUniformQuadSwap", SpvOpGroupNonUniformQuadSwap, 1, pygen_variable_caps_GroupNonUniformQuad, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
   {"SubgroupBallotKHR", SpvOpSubgroupBallotKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu},

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

@@ -208,6 +208,13 @@ class Optimizer {
 // A null pass does nothing to the SPIR-V module to be optimized.
 Optimizer::PassToken CreateNullPass();
 
+// Creates a strip-atomic-counter-memory pass.
+// A strip-atomic-counter-memory pass removes all usages of the
+// AtomicCounterMemory bit in Memory Semantics bitmasks. This bit is a no-op in
+// Vulkan, so isn't needed in that env. And the related capability is not
+// allowed in WebGPU, so it is not allowed in that env.
+Optimizer::PassToken CreateStripAtomicCounterMemoryPass();
+
 // Creates a strip-debug-info pass.
 // A strip-debug-info pass removes all debug instructions (as documented in
 // Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized.

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

@@ -605,3 +605,35 @@ bool spvOpcodeIsDebug(SpvOp opcode) {
       return false;
   }
 }
+
+std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
+  switch (opcode) {
+    case SpvOpMemoryBarrier:
+      return {1};
+    case SpvOpAtomicStore:
+    case SpvOpControlBarrier:
+    case SpvOpAtomicFlagClear:
+    case SpvOpMemoryNamedBarrier:
+      return {2};
+    case SpvOpAtomicLoad:
+    case SpvOpAtomicExchange:
+    case SpvOpAtomicIIncrement:
+    case SpvOpAtomicIDecrement:
+    case SpvOpAtomicIAdd:
+    case SpvOpAtomicISub:
+    case SpvOpAtomicSMin:
+    case SpvOpAtomicUMin:
+    case SpvOpAtomicSMax:
+    case SpvOpAtomicUMax:
+    case SpvOpAtomicAnd:
+    case SpvOpAtomicOr:
+    case SpvOpAtomicXor:
+    case SpvOpAtomicFlagTestAndSet:
+      return {4};
+    case SpvOpAtomicCompareExchange:
+    case SpvOpAtomicCompareExchangeWeak:
+      return {4, 5};
+    default:
+      return {};
+  }
+}

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

@@ -133,4 +133,8 @@ bool spvOpcodeIsScalarizable(SpvOp opcode);
 // Returns true if the given opcode is a debug instruction.
 bool spvOpcodeIsDebug(SpvOp opcode);
 
+// Returns a vector containing the indices of the memory semantics <id>
+// operands for |opcode|.
+std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);
+
 #endif  // SOURCE_OPCODE_H_

+ 2 - 0
3rdparty/spirv-tools/source/opt/CMakeLists.txt

@@ -96,6 +96,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
   simplification_pass.h
   ssa_rewrite_pass.h
   strength_reduction_pass.h
+  strip_atomic_counter_memory_pass.h
   strip_debug_info_pass.h
   strip_reflect_info_pass.h
   struct_cfg_analysis.h
@@ -189,6 +190,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
   simplification_pass.cpp
   ssa_rewrite_pass.cpp
   strength_reduction_pass.cpp
+  strip_atomic_counter_memory_pass.cpp
   strip_debug_info_pass.cpp
   strip_reflect_info_pass.cpp
   struct_cfg_analysis.cpp

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

@@ -271,6 +271,7 @@ bool CCPPass::ReplaceValues() {
     uint32_t id = it.first;
     uint32_t cst_id = it.second;
     if (!IsVaryingValue(cst_id) && id != cst_id) {
+      context()->KillNamesAndDecorates(id);
       retval |= context()->ReplaceAllUsesWith(id, cst_id);
     }
   }

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

@@ -2167,6 +2167,37 @@ FoldingRule VectorShuffleFeedingShuffle() {
   };
 }
 
+// Removes duplicate ids from the interface list of an OpEntryPoint
+// instruction.
+FoldingRule RemoveRedundantOperands() {
+  return [](IRContext*, Instruction* inst,
+            const std::vector<const analysis::Constant*>&) {
+    assert(inst->opcode() == SpvOpEntryPoint &&
+           "Wrong opcode.  Should be OpEntryPoint.");
+    bool has_redundant_operand = false;
+    std::unordered_set<uint32_t> seen_operands;
+    std::vector<Operand> new_operands;
+
+    new_operands.emplace_back(inst->GetOperand(0));
+    new_operands.emplace_back(inst->GetOperand(1));
+    new_operands.emplace_back(inst->GetOperand(2));
+    for (uint32_t i = 3; i < inst->NumOperands(); ++i) {
+      if (seen_operands.insert(inst->GetSingleWordOperand(i)).second) {
+        new_operands.emplace_back(inst->GetOperand(i));
+      } else {
+        has_redundant_operand = true;
+      }
+    }
+
+    if (!has_redundant_operand) {
+      return false;
+    }
+
+    inst->SetInOperands(std::move(new_operands));
+    return true;
+  };
+}
+
 }  // namespace
 
 FoldingRules::FoldingRules() {
@@ -2183,6 +2214,8 @@ FoldingRules::FoldingRules() {
 
   rules_[SpvOpDot].push_back(DotProductDoingExtract());
 
+  rules_[SpvOpEntryPoint].push_back(RemoveRedundantOperands());
+
   rules_[SpvOpExtInst].push_back(RedundantFMix());
 
   rules_[SpvOpFAdd].push_back(RedundantFAdd());

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

@@ -219,6 +219,8 @@ Optimizer& Optimizer::RegisterSizePasses() {
 
 Optimizer& Optimizer::RegisterWebGPUPasses() {
   return RegisterPass(CreateStripDebugInfoPass())
+      .RegisterPass(CreateStripAtomicCounterMemoryPass())
+      .RegisterPass(CreateEliminateDeadConstantPass())
       .RegisterPass(CreateFlattenDecorationPass())
       .RegisterPass(CreateAggressiveDCEPass())
       .RegisterPass(CreateDeadBranchElimPass());
@@ -266,7 +268,9 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
   //
   // Both Pass::name() and Pass::desc() should be static class members so they
   // can be invoked without creating a pass instance.
-  if (pass_name == "strip-debug") {
+  if (pass_name == "strip-atomic-counter-memory") {
+    RegisterPass(CreateStripAtomicCounterMemoryPass());
+  } else if (pass_name == "strip-debug") {
     RegisterPass(CreateStripDebugInfoPass());
   } else if (pass_name == "strip-reflect") {
     RegisterPass(CreateStripReflectInfoPass());
@@ -529,6 +533,11 @@ Optimizer::PassToken CreateNullPass() {
   return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::NullPass>());
 }
 
+Optimizer::PassToken CreateStripAtomicCounterMemoryPass() {
+  return MakeUnique<Optimizer::PassToken::Impl>(
+      MakeUnique<opt::StripAtomicCounterMemoryPass>());
+}
+
 Optimizer::PassToken CreateStripDebugInfoPass() {
   return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::StripDebugInfoPass>());

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

@@ -63,6 +63,7 @@
 #include "source/opt/simplification_pass.h"
 #include "source/opt/ssa_rewrite_pass.h"
 #include "source/opt/strength_reduction_pass.h"
+#include "source/opt/strip_atomic_counter_memory_pass.h"
 #include "source/opt/strip_debug_info_pass.h"
 #include "source/opt/strip_reflect_info_pass.h"
 #include "source/opt/unify_const_pass.h"

+ 57 - 0
3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.cpp

@@ -0,0 +1,57 @@
+// Copyright (c) 2019 Google 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 "source/opt/strip_atomic_counter_memory_pass.h"
+#include "source/opt/ir_context.h"
+
+namespace spvtools {
+namespace opt {
+
+Pass::Status StripAtomicCounterMemoryPass::Process() {
+  bool changed = false;
+  context()->module()->ForEachInst([this, &changed](Instruction* inst) {
+    auto indices = spvOpcodeMemorySemanticsOperandIndices(inst->opcode());
+    if (indices.empty()) return;
+
+    for (auto idx : indices) {
+      auto mem_sem_id = inst->GetSingleWordOperand(idx);
+      const auto& mem_sem_inst =
+          context()->get_def_use_mgr()->GetDef(mem_sem_id);
+      // The spec explicitly says that this id must be an OpConstant
+      auto mem_sem_val = mem_sem_inst->GetSingleWordOperand(2);
+      if (!(mem_sem_val & SpvMemorySemanticsAtomicCounterMemoryMask)) {
+        continue;
+      }
+      mem_sem_val &= ~SpvMemorySemanticsAtomicCounterMemoryMask;
+
+      analysis::Integer int_type(32, false);
+      const analysis::Type* uint32_type =
+          context()->get_type_mgr()->GetRegisteredType(&int_type);
+      auto* new_const = context()->get_constant_mgr()->GetConstant(
+          uint32_type, {mem_sem_val});
+      auto* new_const_inst =
+          context()->get_constant_mgr()->GetDefiningInstruction(new_const);
+      auto new_const_id = new_const_inst->result_id();
+
+      inst->SetOperand(idx, {new_const_id});
+      context()->UpdateDefUse(inst);
+      changed = true;
+    }
+  });
+
+  return changed ? Status::SuccessWithChange : Status::SuccessWithoutChange;
+}
+
+}  // namespace opt
+}  // namespace spvtools

+ 51 - 0
3rdparty/spirv-tools/source/opt/strip_atomic_counter_memory_pass.h

@@ -0,0 +1,51 @@
+// Copyright (c) 2019 Google 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 SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
+#define SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_
+
+#include "source/opt/ir_context.h"
+#include "source/opt/module.h"
+#include "source/opt/pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// Removes the AtomicCounterMemory bit from the value being passed into memory
+// semantics. This bit being set is ignored in Vulkan environments and
+// forbidden WebGPU ones.
+class StripAtomicCounterMemoryPass : public Pass {
+ public:
+  const char* name() const override { return "strip-atomic-counter-memory"; }
+  Status Process() override;
+
+  IRContext::Analysis GetPreservedAnalyses() override {
+    return IRContext::kAnalysisInstrToBlockMapping |
+           IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
+           IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
+           IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
+           IRContext::kAnalysisScalarEvolution |
+           IRContext::kAnalysisRegisterPressure |
+           IRContext::kAnalysisValueNumberTable |
+           IRContext::kAnalysisStructuredCFG |
+           IRContext::kAnalysisBuiltinVarId |
+           IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
+           IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
+  }
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // SOURCE_OPT_STRIP_ATOMIC_COUNT_MEMORY_PASS_H_

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

@@ -24,6 +24,17 @@ namespace spvtools {
 namespace val {
 namespace {
 
+// Returns true if |a| and |b| are instruction defining pointers that point to
+// the same type.
+bool ArePointersToSameType(val::Instruction* a, val::Instruction* b) {
+  if (a->opcode() != SpvOpTypePointer || b->opcode() != SpvOpTypePointer) {
+    return false;
+  }
+
+  uint32_t a_type = a->GetOperandAs<uint32_t>(2);
+  return a_type && (a_type == b->GetOperandAs<uint32_t>(2));
+}
+
 spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
   const auto function_type_id = inst->GetOperandAs<uint32_t>(3);
   const auto function_type = _.FindDef(function_type_id);
@@ -245,7 +256,10 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _,
     const auto parameter_type_id =
         function_type->GetOperandAs<uint32_t>(param_index);
     const auto parameter_type = _.FindDef(parameter_type_id);
-    if (!parameter_type || argument_type->id() != parameter_type->id()) {
+    if (!parameter_type ||
+        (argument_type->id() != parameter_type->id() &&
+         !(_.options()->relax_logical_pointer &&
+           ArePointersToSameType(argument_type, parameter_type)))) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpFunctionCall Argument <id> '" << _.getIdName(argument_id)
              << "'s type does not match Function <id> '"
@@ -287,7 +301,8 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _,
               sc == SpvStorageClassStorageBuffer;
           const bool wg_vptr =
               _.features().variable_pointers && sc == SpvStorageClassWorkgroup;
-          if (!ssbo_vptr && !wg_vptr) {
+          const bool uc_ptr = sc == SpvStorageClassUniformConstant;
+          if (!ssbo_vptr && !wg_vptr && !uc_ptr) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << "Pointer operand " << _.getIdName(argument_id)
                    << " must be a memory object declaration";

+ 30 - 0
3rdparty/spirv-tools/source/val/validate_instruction.cpp

@@ -55,6 +55,18 @@ std::string ToString(const CapabilitySet& capabilities,
   return ss.str();
 }
 
+bool IsValidWebGPUStorageClass(SpvStorageClass storage_class) {
+  return storage_class == SpvStorageClassUniformConstant ||
+         storage_class == SpvStorageClassUniform ||
+         storage_class == SpvStorageClassStorageBuffer ||
+         storage_class == SpvStorageClassInput ||
+         storage_class == SpvStorageClassOutput ||
+         storage_class == SpvStorageClassImage ||
+         storage_class == SpvStorageClassWorkgroup ||
+         storage_class == SpvStorageClassPrivate ||
+         storage_class == SpvStorageClassFunction;
+}
+
 // Returns capabilities that enable an opcode.  An empty result is interpreted
 // as no prohibition of use of the opcode.  If the result is non-empty, then
 // the opcode may only be used if at least one of the capabilities is specified
@@ -483,6 +495,15 @@ spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
     if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) {
       return error;
     }
+
+    if (spvIsWebGPUEnv(_.context()->target_env) &&
+        !IsValidWebGPUStorageClass(storage_class)) {
+      return _.diag(SPV_ERROR_INVALID_BINARY, inst)
+             << "For WebGPU, OpVariable storage class must be one of "
+                "UniformConstant, Uniform, StorageBuffer, Input, Output, "
+                "Image, Workgroup, Private, Function for WebGPU";
+    }
+
     if (storage_class == SpvStorageClassGeneric)
       return _.diag(SPV_ERROR_INVALID_BINARY, inst)
              << "OpVariable storage class cannot be Generic";
@@ -506,6 +527,15 @@ spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
                   "outside of a function";
       }
     }
+  } else if (opcode == SpvOpTypePointer) {
+    const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
+    if (spvIsWebGPUEnv(_.context()->target_env) &&
+        !IsValidWebGPUStorageClass(storage_class)) {
+      return _.diag(SPV_ERROR_INVALID_BINARY, inst)
+             << "For WebGPU, OpTypePointer storage class must be one of "
+                "UniformConstant, Uniform, StorageBuffer, Input, Output, "
+                "Image, Workgroup, Private, Function";
+    }
   }
 
   // SPIR-V Spec 2.16.3: Validation Rules for Kernel Capabilities: The

+ 16 - 0
3rdparty/spirv-tools/source/val/validate_mode_setting.cpp

@@ -344,6 +344,7 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
     case SpvExecutionModeOriginLowerLeft:
     case SpvExecutionModeEarlyFragmentTests:
     case SpvExecutionModeDepthReplacing:
+    case SpvExecutionModeDepthGreater:
     case SpvExecutionModeDepthLess:
     case SpvExecutionModeDepthUnchanged:
       if (!std::all_of(models->begin(), models->end(),
@@ -411,6 +412,21 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
     }
   }
 
+  if (spvIsWebGPUEnv(_.context()->target_env)) {
+    if (mode != SpvExecutionModeOriginUpperLeft &&
+        mode != SpvExecutionModeDepthReplacing &&
+        mode != SpvExecutionModeDepthGreater &&
+        mode != SpvExecutionModeDepthLess &&
+        mode != SpvExecutionModeDepthUnchanged &&
+        mode != SpvExecutionModeLocalSize &&
+        mode != SpvExecutionModeLocalSizeHint) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Execution mode must be one of OriginUpperLeft, "
+                "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
+                "LocalSize, or LocalSizeHint for WebGPU environment.";
+    }
+  }
+
   return SPV_SUCCESS;
 }
 

+ 1 - 0
3rdparty/spirv-tools/test/opt/CMakeLists.txt

@@ -77,6 +77,7 @@ add_spvtools_unittest(TARGET opt
        set_spec_const_default_value_test.cpp
        simplification_test.cpp
        strength_reduction_test.cpp
+       strip_atomic_counter_memory_test.cpp
        strip_debug_info_test.cpp
        strip_reflect_info_test.cpp
        struct_cfg_analysis_test.cpp

+ 29 - 0
3rdparty/spirv-tools/test/opt/ccp_test.cpp

@@ -896,6 +896,35 @@ OpFunctionEnd
   SinglePassRunAndMatch<CCPPass>(text, true);
 }
 
+TEST_F(CCPTest, FoldWithDecoration) {
+  const std::string text = R"(
+; CHECK: OpCapability
+; CHECK-NOT: OpDecorate
+; CHECK: OpFunctionEnd
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main"
+               OpExecutionMode %2 OriginUpperLeft
+               OpSource ESSL 310
+               OpDecorate %3 RelaxedPrecision
+       %void = OpTypeVoid
+          %5 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v3float = OpTypeVector %float 3
+    %float_0 = OpConstant %float 0
+    %v4float = OpTypeVector %float 4
+         %10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+          %2 = OpFunction %void None %5
+         %11 = OpLabel
+          %3 = OpVectorShuffle %v3float %10 %10 0 1 2
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SinglePassRunAndMatch<CCPPass>(text, true);
+}
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools

+ 100 - 0
3rdparty/spirv-tools/test/opt/fold_test.cpp

@@ -6211,6 +6211,106 @@ INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoRes
         9, true)
 ));
 
+using EntryPointFoldingTest =
+::testing::TestWithParam<InstructionFoldingCase<bool>>;
+
+TEST_P(EntryPointFoldingTest, Case) {
+  const auto& tc = GetParam();
+
+  // Build module.
+  std::unique_ptr<IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  ASSERT_NE(nullptr, context);
+
+  // Fold the instruction to test.
+  Instruction* inst = nullptr;
+  inst = &*context->module()->entry_points().begin();
+  assert(inst && "Invalid test.  Could not find entry point instruction to fold.");
+  std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
+  bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
+  EXPECT_EQ(succeeded, tc.expected_result);
+  if (succeeded) {
+    Match(tc.test_body, context.get());
+  }
+}
+
+INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
+::testing::Values(
+    // Test case 0: Basic test 1
+    InstructionFoldingCase<bool>(std::string() +
+                    "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
+                             "OpCapability Shader\n" +
+                        "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
+                             "OpMemoryModel Logical GLSL450\n" +
+                             "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
+                             "OpExecutionMode %2 OriginUpperLeft\n" +
+                             "OpSource GLSL 430\n" +
+                             "OpDecorate %3 Location 0\n" +
+                     "%void = OpTypeVoid\n" +
+                        "%5 = OpTypeFunction %void\n" +
+                    "%float = OpTypeFloat 32\n" +
+                  "%v4float = OpTypeVector %float 4\n" +
+      "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
+                        "%3 = OpVariable %_ptr_Output_v4float Output\n" +
+                      "%int = OpTypeInt 32 1\n" +
+                    "%int_0 = OpConstant %int 0\n" +
+"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
+                        "%2 = OpFunction %void None %5\n" +
+                       "%12 = OpLabel\n" +
+                             "OpReturn\n" +
+                             "OpFunctionEnd\n",
+        9, true),
+    InstructionFoldingCase<bool>(std::string() +
+                    "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
+                             "OpCapability Shader\n" +
+                        "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
+                             "OpMemoryModel Logical GLSL450\n" +
+                             "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
+                             "OpExecutionMode %2 OriginUpperLeft\n" +
+                             "OpSource GLSL 430\n" +
+                             "OpDecorate %3 Location 0\n" +
+                     "%void = OpTypeVoid\n" +
+                        "%5 = OpTypeFunction %void\n" +
+                    "%float = OpTypeFloat 32\n" +
+                  "%v4float = OpTypeVector %float 4\n" +
+      "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
+                        "%3 = OpVariable %_ptr_Output_v4float Output\n" +
+                        "%4 = OpVariable %_ptr_Output_v4float Output\n" +
+                      "%int = OpTypeInt 32 1\n" +
+                    "%int_0 = OpConstant %int 0\n" +
+"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
+                        "%2 = OpFunction %void None %5\n" +
+                       "%12 = OpLabel\n" +
+                             "OpReturn\n" +
+                             "OpFunctionEnd\n",
+        9, true),
+    InstructionFoldingCase<bool>(std::string() +
+                    "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
+                             "OpCapability Shader\n" +
+                        "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
+                             "OpMemoryModel Logical GLSL450\n" +
+                             "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
+                             "OpExecutionMode %2 OriginUpperLeft\n" +
+                             "OpSource GLSL 430\n" +
+                             "OpDecorate %3 Location 0\n" +
+                     "%void = OpTypeVoid\n" +
+                        "%5 = OpTypeFunction %void\n" +
+                    "%float = OpTypeFloat 32\n" +
+                  "%v4float = OpTypeVector %float 4\n" +
+      "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
+                        "%3 = OpVariable %_ptr_Output_v4float Output\n" +
+                        "%4 = OpVariable %_ptr_Output_v4float Output\n" +
+                      "%int = OpTypeInt 32 1\n" +
+                    "%int_0 = OpConstant %int 0\n" +
+"%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
+                        "%2 = OpFunction %void None %5\n" +
+                       "%12 = OpLabel\n" +
+                             "OpReturn\n" +
+                             "OpFunctionEnd\n",
+        9, true)
+));
+
 }  // namespace
 }  // namespace opt
 }  // namespace spvtools

+ 96 - 6
3rdparty/spirv-tools/test/opt/optimizer_test.cpp

@@ -231,9 +231,12 @@ TEST(Optimizer, WebGPUModeSetsCorrectPasses) {
   for (auto name = pass_names.begin(); name != pass_names.end(); ++name)
     registered_passes.push_back(*name);
 
-  std::vector<std::string> expected_passes = {
-      "eliminate-dead-branches", "eliminate-dead-code-aggressive",
-      "flatten-decorations", "strip-debug"};
+  std::vector<std::string> expected_passes = {"eliminate-dead-branches",
+                                              "eliminate-dead-code-aggressive",
+                                              "eliminate-dead-const",
+                                              "flatten-decorations",
+                                              "strip-debug",
+                                              "strip-atomic-counter-memory"};
   std::sort(registered_passes.begin(), registered_passes.end());
   std::sort(expected_passes.begin(), expected_passes.end());
 
@@ -265,7 +268,6 @@ TEST_P(WebGPUPassTest, Ran) {
   class ValidatorOptions validator_options;
   ASSERT_TRUE(opt.Run(binary.data(), binary.size(), &optimized,
                       validator_options, true));
-
   std::string disassembly;
   tools.Disassemble(optimized.data(), optimized.size(), &disassembly);
 
@@ -274,7 +276,7 @@ TEST_P(WebGPUPassTest, Ran) {
 }
 
 INSTANTIATE_TEST_SUITE_P(
-    WebGPU, WebGPUPassTest,
+    Optimizer, WebGPUPassTest,
     ::testing::ValuesIn(std::vector<WebGPUPassCase>{
         // FlattenDecorations
         {// input
@@ -346,7 +348,95 @@ INSTANTIATE_TEST_SUITE_P(
          "OpReturn\n"
          "OpFunctionEnd\n",
          // pass
-         "strip-debug"}}));
+         "strip-debug"},
+        // Eliminate Dead Constants
+        {// input
+         "OpCapability Shader\n"
+         "OpCapability VulkanMemoryModelKHR\n"
+         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
+         "OpMemoryModel Logical VulkanKHR\n"
+         "OpEntryPoint Vertex %func \"shader\"\n"
+         "%u32 = OpTypeInt 32 0\n"
+         "%u32_ptr = OpTypePointer Workgroup %u32\n"
+         "%u32_var = OpVariable %u32_ptr Workgroup\n"
+         "%u32_1 = OpConstant %u32 1\n"
+         "%cross_device = OpConstant %u32 0\n"
+         "%relaxed = OpConstant %u32 0\n"
+         "%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n"
+         "%void = OpTypeVoid\n"
+         "%void_f = OpTypeFunction %void\n"
+         "%func = OpFunction %void None %void_f\n"
+         "%label = OpLabel\n"
+         "OpReturn\n"
+         "OpFunctionEnd\n",
+         // expected
+         "OpCapability Shader\n"
+         "OpCapability VulkanMemoryModelKHR\n"
+         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
+         "OpMemoryModel Logical VulkanKHR\n"
+         "OpEntryPoint Vertex %1 \"shader\"\n"
+         "%uint = OpTypeInt 32 0\n"
+         "%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n"
+         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n"
+         "%void = OpTypeVoid\n"
+         "%10 = OpTypeFunction %void\n"
+         "%1 = OpFunction %void None %10\n"
+         "%11 = OpLabel\n"
+         "OpReturn\n"
+         "OpFunctionEnd\n",
+         "eliminate-dead-const"},
+        // Strip Atomic Counter Memory
+        {// input
+         "OpCapability Shader\n"
+         "OpCapability VulkanMemoryModelKHR\n"
+         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
+         "OpMemoryModel Logical VulkanKHR\n"
+         "OpEntryPoint Vertex %func \"shader\"\n"
+         "%u32 = OpTypeInt 32 0\n"
+         "%u32_ptr = OpTypePointer Workgroup %u32\n"
+         "%u32_var = OpVariable %u32_ptr Workgroup\n"
+         "%u32_0 = OpConstant %u32 0\n"
+         "%u32_1 = OpConstant %u32 1\n"
+         "%cross_device = OpConstant %u32 0\n"
+         "%acquire_release_atomic_counter_workgroup = OpConstant %u32 1288\n"
+         "%void = OpTypeVoid\n"
+         "%void_f = OpTypeFunction %void\n"
+         "%func = OpFunction %void None %void_f\n"
+         "%label = OpLabel\n"
+         "%val0 = OpAtomicStore %u32_var %cross_device "
+         "%acquire_release_atomic_counter_workgroup %u32_1\n"
+         "%val1 = OpAtomicIIncrement %u32 %u32_var %cross_device "
+         "%acquire_release_atomic_counter_workgroup\n"
+         "%val2 = OpAtomicCompareExchange %u32 %u32_var %cross_device "
+         "%acquire_release_atomic_counter_workgroup "
+         "%acquire_release_atomic_counter_workgroup %u32_0 %u32_0\n"
+         "OpReturn\n"
+         "OpFunctionEnd\n",
+         // expected
+         "OpCapability Shader\n"
+         "OpCapability VulkanMemoryModelKHR\n"
+         "OpExtension \"SPV_KHR_vulkan_memory_model\"\n"
+         "OpMemoryModel Logical VulkanKHR\n"
+         "OpEntryPoint Vertex %1 \"shader\"\n"
+         "%uint = OpTypeInt 32 0\n"
+         "%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint\n"
+         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup\n"
+         "%uint_0 = OpConstant %uint 0\n"
+         "%uint_1 = OpConstant %uint 1\n"
+         "%uint_0_0 = OpConstant %uint 0\n"
+         "%void = OpTypeVoid\n"
+         "%10 = OpTypeFunction %void\n"
+         "%uint_264 = OpConstant %uint 264\n"
+         "%1 = OpFunction %void None %10\n"
+         "%11 = OpLabel\n"
+         "OpAtomicStore %4 %uint_0_0 %uint_264 %uint_1\n"
+         "%12 = OpAtomicIIncrement %uint %4 %uint_0_0 %uint_264\n"
+         "%13 = OpAtomicCompareExchange %uint %4 %uint_0_0 %uint_264 %uint_264 "
+         "%uint_0 %uint_0\n"
+         "OpReturn\n"
+         "OpFunctionEnd\n",
+         // pass
+         "strip-atomic-counter-memory"}}));
 
 }  // namespace
 }  // namespace opt

+ 406 - 0
3rdparty/spirv-tools/test/opt/strip_atomic_counter_memory_test.cpp

@@ -0,0 +1,406 @@
+// Copyright (c) 2019 Google 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 <vector>
+
+#include "test/opt/pass_fixture.h"
+#include "test/opt/pass_utils.h"
+
+namespace spvtools {
+namespace opt {
+namespace {
+
+typedef std::tuple<std::string, std::string> StripAtomicCounterMemoryParam;
+
+using MemorySemanticsModified =
+    PassTest<::testing::TestWithParam<StripAtomicCounterMemoryParam>>;
+using NonMemorySemanticsUnmodifiedTest = PassTest<::testing::Test>;
+
+void operator+=(std::vector<const char*>& lhs, const char* rhs) {
+  lhs.push_back(rhs);
+}
+
+std::string GetConstDecl(std::string val) {
+  std::string decl;
+  decl += "%uint_" + val + " = OpConstant %uint " + val;
+  return decl;
+}
+
+std::string GetUnchangedString(std::string(generate_inst)(std::string),
+                               std::string val) {
+  std::string decl = GetConstDecl(val);
+  std::string inst = generate_inst(val);
+
+  std::vector<const char*> result = {
+      // clang-format off
+              "OpCapability Shader",
+              "OpCapability VulkanMemoryModelKHR",
+              "OpExtension \"SPV_KHR_vulkan_memory_model\"",
+              "OpMemoryModel Logical VulkanKHR",
+              "OpEntryPoint Vertex %1 \"shader\"",
+      "%uint = OpTypeInt 32 0",
+"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint",
+         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup",
+    "%uint_0 = OpConstant %uint 0",
+    "%uint_1 = OpConstant %uint 1",
+      "%void = OpTypeVoid",
+         "%8 = OpTypeFunction %void",
+               decl.c_str(),
+         "%1 = OpFunction %void None %8",
+        "%10 = OpLabel",
+               inst.c_str(),
+              "OpReturn",
+              "OpFunctionEnd"
+      // clang-format on
+  };
+  return JoinAllInsts(result);
+}
+
+std::string GetChangedString(std::string(generate_inst)(std::string),
+                             std::string orig, std::string changed) {
+  std::string orig_decl = GetConstDecl(orig);
+  std::string changed_decl = GetConstDecl(changed);
+  std::string inst = generate_inst(changed);
+
+  std::vector<const char*> result = {
+      // clang-format off
+              "OpCapability Shader",
+              "OpCapability VulkanMemoryModelKHR",
+              "OpExtension \"SPV_KHR_vulkan_memory_model\"",
+              "OpMemoryModel Logical VulkanKHR",
+              "OpEntryPoint Vertex %1 \"shader\"",
+      "%uint = OpTypeInt 32 0",
+"%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint",
+         "%4 = OpVariable %_ptr_Workgroup_uint Workgroup",
+    "%uint_0 = OpConstant %uint 0",
+    "%uint_1 = OpConstant %uint 1",
+      "%void = OpTypeVoid",
+         "%8 = OpTypeFunction %void",
+               orig_decl.c_str() };
+  // clang-format on
+  if (changed != "0") result += changed_decl.c_str();
+  result += "%1 = OpFunction %void None %8";
+  result += "%10 = OpLabel";
+  result += inst.c_str();
+  result += "OpReturn";
+  result += "OpFunctionEnd";
+  return JoinAllInsts(result);
+}
+
+std::tuple<std::string, std::string> GetInputAndExpected(
+    std::string(generate_inst)(std::string),
+    StripAtomicCounterMemoryParam param) {
+  std::string orig = std::get<0>(param);
+  std::string changed = std::get<1>(param);
+  std::string input = GetUnchangedString(generate_inst, orig);
+  std::string expected = orig == changed
+                             ? GetUnchangedString(generate_inst, changed)
+                             : GetChangedString(generate_inst, orig, changed);
+  return std::make_tuple(input, expected);
+}
+
+std::string GetOpControlBarrierInst(std::string val) {
+  return "OpControlBarrier %uint_1 %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpControlBarrier) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpControlBarrierInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpMemoryBarrierInst(std::string val) {
+  return "OpMemoryBarrier %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpMemoryBarrier) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpMemoryBarrierInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicLoadInst(std::string val) {
+  return "%11 = OpAtomicLoad %uint %4 %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicLoad) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicLoadInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicStoreInst(std::string val) {
+  return "OpAtomicStore %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicStore) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicStoreInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicExchangeInst(std::string val) {
+  return "%11 = OpAtomicExchange %uint %4 %uint_1 %uint_" + val + " %uint_0";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicExchange) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicExchangeInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicCompareExchangeInst(std::string val) {
+  return "%11 = OpAtomicCompareExchange %uint %4 %uint_1 %uint_" + val +
+         " %uint_" + val + " %uint_0 %uint_0";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicCompareExchange) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicCompareExchangeInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicCompareExchangeWeakInst(std::string val) {
+  return "%11 = OpAtomicCompareExchangeWeak %uint %4 %uint_1 %uint_" + val +
+         " %uint_" + val + " %uint_0 %uint_0";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicCompareExchangeWeak) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicCompareExchangeWeakInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicIIncrementInst(std::string val) {
+  return "%11 = OpAtomicIIncrement %uint %4 %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicIIncrement) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicIIncrementInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicIDecrementInst(std::string val) {
+  return "%11 = OpAtomicIDecrement %uint %4 %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicIDecrement) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicIDecrementInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicIAddInst(std::string val) {
+  return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicIAdd) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicIAddInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicISubInst(std::string val) {
+  return "%11 = OpAtomicISub %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicISub) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicISubInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicSMinInst(std::string val) {
+  return "%11 = OpAtomicSMin %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicSMin) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicSMinInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicUMinInst(std::string val) {
+  return "%11 = OpAtomicUMin %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicUMin) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicUMinInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicSMaxInst(std::string val) {
+  return "%11 = OpAtomicSMax %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicSMax) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicSMaxInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicUMaxInst(std::string val) {
+  return "%11 = OpAtomicUMax %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicUMax) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicUMaxInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicAndInst(std::string val) {
+  return "%11 = OpAtomicAnd %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicAnd) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicAndInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicOrInst(std::string val) {
+  return "%11 = OpAtomicOr %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicOr) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicOrInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicXorInst(std::string val) {
+  return "%11 = OpAtomicXor %uint %4 %uint_1 %uint_" + val + " %uint_1";
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicXor) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicXorInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicFlagTestAndSetInst(std::string val) {
+  return "%11 = OpAtomicFlagTestAndSet %uint %4 %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicFlagTestAndSet) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicFlagTestAndSetInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpAtomicFlagClearInst(std::string val) {
+  return "OpAtomicFlagClear %4 %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpAtomicFlagClear) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpAtomicFlagClearInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetOpMemoryNamedBarrierInst(std::string val) {
+  return "OpMemoryNamedBarrier %4 %uint_1 %uint_" + val;
+}
+
+TEST_P(MemorySemanticsModified, OpMemoryNamedBarrier) {
+  std::string input, expected;
+  std::tie(input, expected) =
+      GetInputAndExpected(GetOpMemoryNamedBarrierInst, GetParam());
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+// clang-format off
+INSTANTIATE_TEST_SUITE_P(
+    StripAtomicCounterMemoryTest, MemorySemanticsModified,
+    ::testing::ValuesIn(std::vector<StripAtomicCounterMemoryParam>({
+       std::make_tuple("1024", "0"),
+       std::make_tuple("5", "5"),
+       std::make_tuple("1288", "264"),
+       std::make_tuple("264", "264")
+    })));
+// clang-format on
+
+std::string GetNoMemorySemanticsPresentInst(std::string val) {
+  return "%11 = OpVariable %_ptr_Workgroup_uint Workgroup %uint_" + val;
+}
+
+TEST_F(NonMemorySemanticsUnmodifiedTest, NoMemorySemanticsPresent) {
+  std::string input, expected;
+  StripAtomicCounterMemoryParam param = std::make_tuple("1288", "1288");
+  std::tie(input, expected) =
+      GetInputAndExpected(GetNoMemorySemanticsPresentInst, param);
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+std::string GetMemorySemanticsPresentInst(std::string val) {
+  return "%11 = OpAtomicIAdd %uint %4 %uint_1 %uint_" + val + " %uint_1288";
+}
+
+TEST_F(NonMemorySemanticsUnmodifiedTest, MemorySemanticsPresent) {
+  std::string input, expected;
+  StripAtomicCounterMemoryParam param = std::make_tuple("1288", "264");
+  std::tie(input, expected) =
+      GetInputAndExpected(GetMemorySemanticsPresentInst, param);
+  SinglePassRunAndCheck<StripAtomicCounterMemoryPass>(input, expected,
+                                                      /* skip_nop = */ false);
+}
+
+}  // namespace
+}  // namespace opt
+}  // namespace spvtools

+ 2 - 0
3rdparty/spirv-tools/test/val/val_decoration_test.cpp

@@ -3023,6 +3023,8 @@ TEST_F(ValidateDecorations,
             OpMemoryModel Logical GLSL450
             OpEntryPoint Fragment %1 "main"
             OpExecutionMode %1 OriginUpperLeft
+            OpDecorate %struct Block
+            OpMemberDecorate %struct 0 Offset 0
 
     %void = OpTypeVoid
   %voidfn = OpTypeFunction %void

+ 12 - 10
3rdparty/spirv-tools/test/val/val_function_test.cpp

@@ -321,13 +321,15 @@ TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationNoVariablePointers) {
   std::string spirv = GenerateShaderAccessChain(storage_class, "", "");
 
   const std::vector<std::string> valid_storage_classes = {
-      "UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"};
+      "Function", "Private", "Workgroup", "AtomicCounter"};
   bool valid_sc =
       std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
                 storage_class) != valid_storage_classes.end();
 
   CompileSuccessfully(spirv);
-  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  spv_result_t expected_result =
+      storage_class == "UniformConstant" ? SPV_SUCCESS : SPV_ERROR_INVALID_ID;
+  EXPECT_EQ(expected_result, ValidateInstructions());
   if (valid_sc) {
     EXPECT_THAT(
         getDiagnosticString(),
@@ -338,7 +340,7 @@ TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationNoVariablePointers) {
       EXPECT_THAT(getDiagnosticString(),
                   HasSubstr("StorageBuffer pointer operand 2[%gep] requires a "
                             "variable pointers capability"));
-    } else {
+    } else if (storage_class != "UniformConstant") {
       EXPECT_THAT(
           getDiagnosticString(),
           HasSubstr("Invalid storage class for pointer operand 2[%gep]"));
@@ -355,12 +357,12 @@ TEST_P(ValidateFunctionCall,
       "OpExtension \"SPV_KHR_variable_pointers\"");
 
   const std::vector<std::string> valid_storage_classes = {
-      "UniformConstant", "Function",      "Private",
-      "Workgroup",       "StorageBuffer", "AtomicCounter"};
+      "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
   bool valid_sc =
       std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
                 storage_class) != valid_storage_classes.end();
-  bool validate = storage_class == "StorageBuffer";
+  bool validate =
+      storage_class == "StorageBuffer" || storage_class == "UniformConstant";
 
   CompileSuccessfully(spirv);
   if (validate) {
@@ -388,13 +390,13 @@ TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationVariablePointers) {
                                 "OpExtension \"SPV_KHR_variable_pointers\"");
 
   const std::vector<std::string> valid_storage_classes = {
-      "UniformConstant", "Function",      "Private",
-      "Workgroup",       "StorageBuffer", "AtomicCounter"};
+      "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
   bool valid_sc =
       std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
                 storage_class) != valid_storage_classes.end();
-  bool validate =
-      storage_class == "StorageBuffer" || storage_class == "Workgroup";
+  bool validate = storage_class == "StorageBuffer" ||
+                  storage_class == "Workgroup" ||
+                  storage_class == "UniformConstant";
 
   CompileSuccessfully(spirv);
   if (validate) {

+ 48 - 7
3rdparty/spirv-tools/test/val/val_modes_test.cpp

@@ -531,16 +531,24 @@ TEST_P(ValidateModeExecution, ExecutionMode) {
 
   std::ostringstream sstr;
   sstr << "OpCapability Shader\n";
-  sstr << "OpCapability Geometry\n";
-  sstr << "OpCapability Tessellation\n";
-  sstr << "OpCapability TransformFeedback\n";
-  if (!spvIsVulkanEnv(env)) {
+  if (!spvIsWebGPUEnv(env)) {
+    sstr << "OpCapability Geometry\n";
+    sstr << "OpCapability Tessellation\n";
+    sstr << "OpCapability TransformFeedback\n";
+  }
+  if (!spvIsVulkanOrWebGPUEnv(env)) {
     sstr << "OpCapability Kernel\n";
     if (env == SPV_ENV_UNIVERSAL_1_3) {
       sstr << "OpCapability SubgroupDispatch\n";
     }
   }
-  sstr << "OpMemoryModel Logical GLSL450\n";
+  if (spvIsWebGPUEnv(env)) {
+    sstr << "OpCapability VulkanMemoryModelKHR\n";
+    sstr << "OpExtension \"SPV_KHR_vulkan_memory_model\"\n";
+    sstr << "OpMemoryModel Logical VulkanKHR\n";
+  } else {
+    sstr << "OpMemoryModel Logical GLSL450\n";
+  }
   sstr << "OpEntryPoint " << model << " %main \"main\"\n";
   if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 ||
       mode.find("SubgroupsPerWorkgroupId") == 0) {
@@ -657,8 +665,8 @@ INSTANTIATE_TEST_SUITE_P(
             Values("Geometry", "TessellationControl", "TessellationEvaluation",
                    "GLCompute", "Vertex", "Kernel"),
             Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
-                   "EarlyFragmentTests", "DepthReplacing", "DepthLess",
-                   "DepthUnchanged"),
+                   "EarlyFragmentTests", "DepthReplacing", "DepthGreater",
+                   "DepthLess", "DepthUnchanged"),
             Values(SPV_ENV_UNIVERSAL_1_0)));
 
 INSTANTIATE_TEST_SUITE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution,
@@ -706,6 +714,39 @@ INSTANTIATE_TEST_SUITE_P(
                    "SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"),
             Values(SPV_ENV_UNIVERSAL_1_3)));
 
+INSTANTIATE_TEST_SUITE_P(ValidateModeGLComputeWebGPUWhitelistGood,
+                         ValidateModeExecution,
+                         Combine(Values(SPV_SUCCESS), Values(""),
+                                 Values("GLCompute"), Values("LocalSize 1 1 1"),
+                                 Values(SPV_ENV_WEBGPU_0)));
+
+INSTANTIATE_TEST_SUITE_P(
+    ValidateModeGLComputeWebGPUWhitelistBad, ValidateModeExecution,
+    Combine(Values(SPV_ERROR_INVALID_DATA),
+            Values("Execution mode must be one of OriginUpperLeft, "
+                   "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
+                   "LocalSize, or LocalSizeHint for WebGPU environment"),
+            Values("GLCompute"), Values("LocalSizeId %int1 %int1 %int1"),
+            Values(SPV_ENV_WEBGPU_0)));
+
+INSTANTIATE_TEST_SUITE_P(
+    ValidateModeFragmentWebGPUWhitelistGood, ValidateModeExecution,
+    Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"),
+            Values("OriginUpperLeft", "DepthReplacing", "DepthGreater",
+                   "DepthLess", "DepthUnchanged"),
+            Values(SPV_ENV_WEBGPU_0)));
+
+INSTANTIATE_TEST_SUITE_P(
+    ValidateModeFragmentWebGPUWhitelistBad, ValidateModeExecution,
+    Combine(Values(SPV_ERROR_INVALID_DATA),
+            Values("Execution mode must be one of OriginUpperLeft, "
+                   "DepthReplacing, DepthGreater, DepthLess, DepthUnchanged, "
+                   "LocalSize, or LocalSizeHint for WebGPU environment"),
+            Values("Fragment"),
+            Values("PixelCenterInteger", "OriginLowerLeft",
+                   "EarlyFragmentTests"),
+            Values(SPV_ENV_WEBGPU_0)));
+
 TEST_F(ValidateModeExecution, MeshNVLocalSize) {
   const std::string spirv = R"(
 OpCapability Shader

+ 128 - 0
3rdparty/spirv-tools/test/val/val_storage_test.cpp

@@ -26,7 +26,10 @@ namespace val {
 namespace {
 
 using ::testing::HasSubstr;
+using ::testing::Values;
 using ValidateStorage = spvtest::ValidateBase<std::string>;
+using ValidateStorageClass =
+    spvtest::ValidateBase<std::tuple<std::string, bool, bool, std::string>>;
 
 TEST_F(ValidateStorage, FunctionStorageInsideFunction) {
   char str[] = R"(
@@ -186,6 +189,131 @@ TEST_F(ValidateStorage, GenericVariableInsideFunction) {
               HasSubstr("OpVariable storage class cannot be Generic"));
 }
 
+TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParam) {
+  const auto str = R"(
+          OpCapability Shader
+          OpCapability Linkage
+          OpMemoryModel Logical GLSL450
+%intt   = OpTypeInt 32 1
+%voidt  = OpTypeVoid
+%ptrt   = OpTypePointer Function %intt
+%vfunct = OpTypeFunction %voidt
+%vifunct = OpTypeFunction %voidt %ptrt
+%wgroupptrt = OpTypePointer Workgroup %intt
+%wgroup = OpVariable %wgroupptrt Workgroup
+%main   = OpFunction %voidt None %vfunct
+%mainl  = OpLabel
+%ret    = OpFunctionCall %voidt %func %wgroup
+          OpReturn
+          OpFunctionEnd
+%func   = OpFunction %voidt None %vifunct
+%arg    = OpFunctionParameter %ptrt
+%funcl  = OpLabel
+          OpReturn
+          OpFunctionEnd
+)";
+  CompileSuccessfully(str);
+  getValidatorOptions()->relax_logical_pointer = true;
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParamBad) {
+  const auto str = R"(
+          OpCapability Shader
+          OpCapability Linkage
+          OpMemoryModel Logical GLSL450
+%floatt = OpTypeFloat 32
+%intt   = OpTypeInt 32 1
+%voidt  = OpTypeVoid
+%ptrt   = OpTypePointer Function %intt
+%vfunct = OpTypeFunction %voidt
+%vifunct = OpTypeFunction %voidt %ptrt
+%wgroupptrt = OpTypePointer Workgroup %floatt
+%wgroup = OpVariable %wgroupptrt Workgroup
+%main   = OpFunction %voidt None %vfunct
+%mainl  = OpLabel
+%ret    = OpFunctionCall %voidt %func %wgroup
+          OpReturn
+          OpFunctionEnd
+%func   = OpFunction %voidt None %vifunct
+%arg    = OpFunctionParameter %ptrt
+%funcl  = OpLabel
+          OpReturn
+          OpFunctionEnd
+)";
+  CompileSuccessfully(str);
+  getValidatorOptions()->relax_logical_pointer = true;
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("OpFunctionCall Argument <id> '"));
+}
+
+std::string GetVarDeclStr(const std::string& storage_class) {
+  if (storage_class != "Output" && storage_class != "Private" &&
+      storage_class != "Function") {
+    return "%var    = OpVariable %ptrt " + storage_class + "\n";
+  } else {
+    return "%var    = OpVariable %ptrt " + storage_class + " %null\n";
+  }
+}
+
+TEST_P(ValidateStorageClass, WebGPU) {
+  std::string storage_class = std::get<0>(GetParam());
+  bool is_local = std::get<1>(GetParam());
+  bool is_valid = std::get<2>(GetParam());
+  std::string error = std::get<3>(GetParam());
+
+  std::string str = R"(
+          OpCapability Shader
+          OpCapability VulkanMemoryModelKHR
+          OpExtension "SPV_KHR_vulkan_memory_model"
+          OpMemoryModel Logical VulkanKHR
+          OpEntryPoint Fragment %func "func"
+          OpExecutionMode %func OriginUpperLeft
+%intt   = OpTypeInt 32 1
+%voidt  = OpTypeVoid
+%vfunct = OpTypeFunction %voidt
+%null   = OpConstantNull %intt
+)";
+  str += "%ptrt   = OpTypePointer " + storage_class + " %intt\n";
+  if (!is_local) str += GetVarDeclStr(storage_class);
+  str += R"(
+%func   = OpFunction %voidt None %vfunct
+%funcl  = OpLabel
+)";
+  if (is_local) str += GetVarDeclStr(storage_class);
+  str += R"(
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(str, SPV_ENV_WEBGPU_0);
+  if (is_valid) {
+    ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0));
+  } else {
+    ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions(SPV_ENV_WEBGPU_0));
+    EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
+  }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    StorageClass, ValidateStorageClass,
+    Values(std::make_tuple("UniformConstant", false, true, ""),
+           std::make_tuple("Uniform", false, true, ""),
+           std::make_tuple("StorageBuffer", false, true, ""),
+           std::make_tuple("Input", false, true, ""),
+           std::make_tuple("Output", false, true, ""),
+           std::make_tuple("Image", false, true, ""),
+           std::make_tuple("Workgroup", false, true, ""),
+           std::make_tuple("Private", false, true, ""),
+           std::make_tuple("Function", true, true, ""),
+           std::make_tuple(
+               "CrossWorkgroup", false, false,
+               "For WebGPU, OpTypePointer storage class must be one of"),
+           std::make_tuple(
+               "PushConstant", false, false,
+               "For WebGPU, OpTypePointer storage class must be one of")));
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools

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

@@ -340,6 +340,8 @@ Options (in lexicographical order):
                This options should be used rarely, and with caution.
   --strength-reduction
                Replaces instructions with equivalent and less expensive ones.
+  --strip-atomic-counter-memory
+               Removes AtomicCountMemory bit from memory semantics values.
   --strip-debug
                Remove all debug instructions.
   --strip-reflect