Przeglądaj źródła

Updated spirv-tools.

Бранимир Караџић 6 lat temu
rodzic
commit
eabaa485af
45 zmienionych plików z 918 dodań i 334 usunięć
  1. 1 1
      3rdparty/spirv-tools/include/generated/DebugInfo.h
  2. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  3. 4 1
      3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
  4. 1 1
      3rdparty/spirv-tools/include/generated/debuginfo.insts.inc
  5. 2 1
      3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
  6. 2 1
      3rdparty/spirv-tools/include/generated/extension_enum.inc
  7. 1 1
      3rdparty/spirv-tools/include/generated/generators.inc
  8. 1 1
      3rdparty/spirv-tools/include/generated/glsl.std.450.insts.inc
  9. 1 1
      3rdparty/spirv-tools/include/generated/opencl.std.insts.inc
  10. 3 1
      3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
  11. 1 1
      3rdparty/spirv-tools/include/generated/spv-amd-gcn-shader.insts.inc
  12. 1 1
      3rdparty/spirv-tools/include/generated/spv-amd-shader-ballot.insts.inc
  13. 1 1
      3rdparty/spirv-tools/include/generated/spv-amd-shader-explicit-vertex-parameter.insts.inc
  14. 1 1
      3rdparty/spirv-tools/include/generated/spv-amd-shader-trinary-minmax.insts.inc
  15. 33 8
      3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp
  16. 4 15
      3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.cpp
  17. 0 3
      3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.h
  18. 12 10
      3rdparty/spirv-tools/source/opt/merge_return_pass.cpp
  19. 13 13
      3rdparty/spirv-tools/source/opt/merge_return_pass.h
  20. 7 0
      3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp
  21. 3 0
      3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.h
  22. 9 6
      3rdparty/spirv-tools/source/val/function.cpp
  23. 3 4
      3rdparty/spirv-tools/source/val/validate_annotation.cpp
  24. 56 24
      3rdparty/spirv-tools/source/val/validate_atomics.cpp
  25. 39 26
      3rdparty/spirv-tools/source/val/validate_cfg.cpp
  26. 38 30
      3rdparty/spirv-tools/source/val/validate_derivatives.cpp
  27. 71 5
      3rdparty/spirv-tools/source/val/validate_image.cpp
  28. 56 0
      3rdparty/spirv-tools/test/opt/aggressive_dead_code_elim_test.cpp
  29. 30 28
      3rdparty/spirv-tools/test/opt/inst_bindless_check_test.cpp
  30. 57 0
      3rdparty/spirv-tools/test/opt/local_ssa_elim_test.cpp
  31. 51 0
      3rdparty/spirv-tools/test/opt/pass_merge_return_test.cpp
  32. 0 2
      3rdparty/spirv-tools/test/scripts/test_compact_ids.py
  33. 0 2
      3rdparty/spirv-tools/test/tools/spirv_test_framework.py
  34. 27 21
      3rdparty/spirv-tools/test/val/val_atomics_test.cpp
  35. 174 0
      3rdparty/spirv-tools/test/val/val_cfg_test.cpp
  36. 3 4
      3rdparty/spirv-tools/test/val/val_derivatives_test.cpp
  37. 1 1
      3rdparty/spirv-tools/test/val/val_id_test.cpp
  38. 141 44
      3rdparty/spirv-tools/test/val/val_image_test.cpp
  39. 0 1
      3rdparty/spirv-tools/utils/check_copyright.py
  40. 0 2
      3rdparty/spirv-tools/utils/check_symbol_exports.py
  41. 65 61
      3rdparty/spirv-tools/utils/generate_grammar_tables.py
  42. 2 3
      3rdparty/spirv-tools/utils/generate_language_headers.py
  43. 2 3
      3rdparty/spirv-tools/utils/generate_registry_tables.py
  44. 0 2
      3rdparty/spirv-tools/utils/generate_vim_syntax.py
  45. 0 2
      3rdparty/spirv-tools/utils/update_build_version.py

+ 1 - 1
3rdparty/spirv-tools/include/generated/DebugInfo.h

@@ -134,4 +134,4 @@ enum DebugInfoDebugOperation {
 }
 #endif
 
-#endif // SPIRV_EXTINST_DebugInfo_H_
+#endif // SPIRV_EXTINST_DebugInfo_H_

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

@@ -1 +1 @@
-"v2019.4-dev", "SPIRV-Tools v2019.4-dev v2019.3-90-g76b75c40"
+"v2019.4-dev", "SPIRV-Tools v2019.4-dev v2019.3-99-g65f49dfc"

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

@@ -32,6 +32,7 @@ static const SpvCapability pygen_variable_caps_PipeStorage[] = {SpvCapabilityPip
 static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes};
 static const SpvCapability pygen_variable_caps_RayTracingNV[] = {SpvCapabilityRayTracingNV};
 static const SpvCapability pygen_variable_caps_Shader[] = {SpvCapabilityShader};
+static const SpvCapability pygen_variable_caps_ShaderClockKHR[] = {SpvCapabilityShaderClockKHR};
 static const SpvCapability pygen_variable_caps_SparseResidency[] = {SpvCapabilitySparseResidency};
 static const SpvCapability pygen_variable_caps_SubgroupAvcMotionEstimationINTEL[] = {SpvCapabilitySubgroupAvcMotionEstimationINTEL};
 static const SpvCapability pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationChromaINTEL[] = {SpvCapabilitySubgroupAvcMotionEstimationINTEL, SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL};
@@ -51,6 +52,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_shader_int
 static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_decorate_stringSPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_decorate_string, spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
 static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
+static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock};
 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_NV_cooperative_matrix[] = {spvtools::Extension::kSPV_NV_cooperative_matrix};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_NV_mesh_shader};
@@ -419,6 +421,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"GroupSMaxNonUniformAMD", SpvOpGroupSMaxNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu, 0xffffffffu},
   {"FragmentMaskFetchAMD", SpvOpFragmentMaskFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 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_AMD_shader_fragment_mask, 0xffffffffu, 0xffffffffu},
   {"FragmentFetchAMD", SpvOpFragmentFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu, 0xffffffffu},
+  {"ReadClockKHR", SpvOpReadClockKHR, 1, pygen_variable_caps_ShaderClockKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_clock, 0xffffffffu, 0xffffffffu},
   {"ImageSampleFootprintNV", SpvOpImageSampleFootprintNV, 1, pygen_variable_caps_ImageFootprintNV, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_image_footprint, 0xffffffffu, 0xffffffffu},
   {"GroupNonUniformPartitionNV", SpvOpGroupNonUniformPartitionNV, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_subgroup_partitioned, 0xffffffffu, 0xffffffffu},
   {"WritePackedPrimitiveIndices4x8NV", SpvOpWritePackedPrimitiveIndices4x8NV, 1, pygen_variable_caps_MeshShadingNV, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_mesh_shader, 0xffffffffu, 0xffffffffu},
@@ -583,4 +586,4 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"SubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"SubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"SubgroupAvcSicGetInterRawSadsINTEL", SpvOpSubgroupAvcSicGetInterRawSadsINTEL, 1, pygen_variable_caps_SubgroupAvcMotionEstimationINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}
-};
+};

+ 1 - 1
3rdparty/spirv-tools/include/generated/debuginfo.insts.inc

@@ -35,4 +35,4 @@ static const spv_ext_inst_desc_t debuginfo_entries[] = {
   {"DebugExpression", 31, 0, nullptr, {SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
   {"DebugMacroDef", 32, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
   {"DebugMacroUndef", 33, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
-};
+};

Plik diff jest za duży
+ 2 - 1
3rdparty/spirv-tools/include/generated/enum_string_mapping.inc


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

@@ -32,6 +32,7 @@ kSPV_KHR_no_integer_wrap_decoration,
 kSPV_KHR_post_depth_coverage,
 kSPV_KHR_shader_atomic_counter_ops,
 kSPV_KHR_shader_ballot,
+kSPV_KHR_shader_clock,
 kSPV_KHR_shader_draw_parameters,
 kSPV_KHR_storage_buffer_storage_class,
 kSPV_KHR_subgroup_vote,
@@ -51,4 +52,4 @@ kSPV_NV_shader_subgroup_partitioned,
 kSPV_NV_shading_rate,
 kSPV_NV_stereo_view_rendering,
 kSPV_NV_viewport_array2,
-kSPV_VALIDATOR_ignore_type_decl_unique
+kSPV_VALIDATOR_ignore_type_decl_unique

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

@@ -20,4 +20,4 @@
 {19, "Clay", "Clay Shader Compiler", "Clay Clay Shader Compiler"},
 {20, "W3C WebGPU Group", "WHLSL Shader Translator", "W3C WebGPU Group WHLSL Shader Translator"},
 {21, "Google", "Clspv", "Google Clspv"},
-{22, "Google", "MLIR SPIR-V Serializer", "Google MLIR SPIR-V Serializer"},
+{22, "Google", "MLIR SPIR-V Serializer", "Google MLIR SPIR-V Serializer"},

+ 1 - 1
3rdparty/spirv-tools/include/generated/glsl.std.450.insts.inc

@@ -83,4 +83,4 @@ static const spv_ext_inst_desc_t glsl_entries[] = {
   {"NMin", 79, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"NMax", 80, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"NClamp", 81, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
-};
+};

+ 1 - 1
3rdparty/spirv-tools/include/generated/opencl.std.insts.inc

@@ -163,4 +163,4 @@ static const spv_ext_inst_desc_t opencl_entries[] = {
   {"u_abs_diff", 202, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"u_mul_hi", 203, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"u_mad_hi", 204, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
-};
+};

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

@@ -114,6 +114,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_no_integer_wrap_dec
 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_shader_atomic_counter_ops[] = {spvtools::Extension::kSPV_KHR_shader_atomic_counter_ops};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
+static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock};
 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};
@@ -781,6 +782,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"FragmentMaskAMD", 5010, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, {}, 0xffffffffu, 0xffffffffu},
   {"StencilExportEXT", 5013, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu},
   {"ImageReadWriteLodAMD", 5015, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_image_load_store_lod, {}, 0xffffffffu, 0xffffffffu},
+  {"ShaderClockKHR", 5055, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_clock, {}, 0xffffffffu, 0xffffffffu},
   {"SampleMaskOverrideCoverageNV", 5249, 1, pygen_variable_caps_SampleRateShading, 1, pygen_variable_exts_SPV_NV_sample_mask_override_coverage, {}, 0xffffffffu, 0xffffffffu},
   {"GeometryShaderPassthroughNV", 5251, 1, pygen_variable_caps_Geometry, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu, 0xffffffffu},
   {"ShaderViewportIndexLayerEXT", 5254, 1, pygen_variable_caps_MultiViewport, 2, pygen_variable_exts_SPV_EXT_shader_viewport_index_layerSPV_NV_viewport_array2, {}, 0xffffffffu, 0xffffffffu},
@@ -921,4 +923,4 @@ static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = {
   {SPV_OPERAND_TYPE_OPTIONAL_IMAGE, ARRAY_SIZE(pygen_variable_ImageOperandsEntries), pygen_variable_ImageOperandsEntries},
   {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries},
   {SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER, ARRAY_SIZE(pygen_variable_AccessQualifierEntries), pygen_variable_AccessQualifierEntries}
-};
+};

+ 1 - 1
3rdparty/spirv-tools/include/generated/spv-amd-gcn-shader.insts.inc

@@ -4,4 +4,4 @@ static const spv_ext_inst_desc_t spv_amd_gcn_shader_entries[] = {
   {"CubeFaceIndexAMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"CubeFaceCoordAMD", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"TimeAMD", 3, 0, nullptr, {SPV_OPERAND_TYPE_NONE}}
-};
+};

+ 1 - 1
3rdparty/spirv-tools/include/generated/spv-amd-shader-ballot.insts.inc

@@ -5,4 +5,4 @@ static const spv_ext_inst_desc_t spv_amd_shader_ballot_entries[] = {
   {"SwizzleInvocationsMaskedAMD", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"WriteInvocationAMD", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"MbcntAMD", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
-};
+};

+ 1 - 1
3rdparty/spirv-tools/include/generated/spv-amd-shader-explicit-vertex-parameter.insts.inc

@@ -2,4 +2,4 @@
 
 static const spv_ext_inst_desc_t spv_amd_shader_explicit_vertex_parameter_entries[] = {
   {"InterpolateAtVertexAMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
-};
+};

+ 1 - 1
3rdparty/spirv-tools/include/generated/spv-amd-shader-trinary-minmax.insts.inc

@@ -10,4 +10,4 @@ static const spv_ext_inst_desc_t spv_amd_shader_trinary_minmax_entries[] = {
   {"FMid3AMD", 7, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"UMid3AMD", 8, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
   {"SMid3AMD", 9, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
-};
+};

+ 33 - 8
3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp

@@ -490,6 +490,28 @@ bool AggressiveDCEPass::AggressiveDCE(Function* func) {
         ProcessLoad(varId);
       }
     }
+
+    // Add OpDecorateId instructions that apply to this instruction to the work
+    // list.  We use the decoration manager to look through the group
+    // decorations to get to the OpDecorate* instructions themselves.
+    auto decorations =
+        get_decoration_mgr()->GetDecorationsFor(liveInst->result_id(), false);
+    for (Instruction* dec : decorations) {
+      // We only care about OpDecorateId instructions because the are the only
+      // decorations that will reference an id that will have to be kept live
+      // because of that use.
+      if (dec->opcode() != SpvOpDecorateId) {
+        continue;
+      }
+      if (dec->GetSingleWordInOperand(1) ==
+          SpvDecorationHlslCounterBufferGOOGLE) {
+        // These decorations should not force the use id to be live.  It will be
+        // removed if either the target or the in operand are dead.
+        continue;
+      }
+      AddToWorklist(dec);
+    }
+
     worklist_.pop();
   }
 
@@ -618,14 +640,6 @@ Pass::Status AggressiveDCEPass::ProcessImpl() {
   // return unmodified.
   if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
 
-  // If the decoration manager is kept live then the context will try to keep it
-  // up to date.  ADCE deals with group decorations by changing the operands in
-  // |OpGroupDecorate| instruction directly without informing the decoration
-  // manager.  This can put it in an invalid state which will cause an error
-  // when the context tries to update it.  To avoid this problem invalidate
-  // the decoration manager upfront.
-  context()->InvalidateAnalyses(IRContext::Analysis::kAnalysisDecorations);
-
   // Eliminate Dead functions.
   bool modified = EliminateDeadFunctions();
 
@@ -635,6 +649,17 @@ Pass::Status AggressiveDCEPass::ProcessImpl() {
   ProcessFunction pfn = [this](Function* fp) { return AggressiveDCE(fp); };
   modified |= context()->ProcessEntryPointCallTree(pfn);
 
+  // If the decoration manager is kept live then the context will try to keep it
+  // up to date.  ADCE deals with group decorations by changing the operands in
+  // |OpGroupDecorate| instruction directly without informing the decoration
+  // manager.  This can put it in an invalid state which will cause an error
+  // when the context tries to update it.  To avoid this problem invalidate
+  // the decoration manager upfront.
+  //
+  // We kill it at now because it is used when processing the entry point
+  // functions.
+  context()->InvalidateAnalyses(IRContext::Analysis::kAnalysisDecorations);
+
   // Process module-level instructions. Now that all live instructions have
   // been marked, it is safe to remove dead global values.
   modified |= ProcessGlobalValues();

+ 4 - 15
3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.cpp

@@ -398,20 +398,9 @@ void InstBindlessCheckPass::GenInitCheckCode(
 void InstBindlessCheckPass::InitializeInstBindlessCheck() {
   // Initialize base class
   InitializeInstrument();
-  // Look for related extensions
-  ext_descriptor_indexing_defined_ = false;
-  for (auto& ei : get_module()->extensions()) {
-    const char* ext_name =
-        reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
-    if (strcmp(ext_name, "SPV_EXT_descriptor_indexing") == 0) {
-      ext_descriptor_indexing_defined_ = true;
-      break;
-    }
-  }
-  // If descriptor indexing extension and runtime array length support enabled,
-  // create variable mappings. Length support is always enabled if descriptor
-  // init check is enabled.
-  if (ext_descriptor_indexing_defined_ && input_length_enabled_)
+  // If runtime array length support enabled, create variable mappings. Length
+  // support is always enabled if descriptor init check is enabled.
+  if (input_length_enabled_)
     for (auto& anno : get_module()->annotations())
       if (anno.opcode() == SpvOpDecorate) {
         if (anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet)
@@ -433,7 +422,7 @@ Pass::Status InstBindlessCheckPass::ProcessImpl() {
                                   new_blocks);
       };
   bool modified = InstProcessEntryPointCallTree(pfn);
-  if (ext_descriptor_indexing_defined_ && input_init_enabled_) {
+  if (input_init_enabled_) {
     // Perform descriptor initialization check on each entry point function in
     // module
     pfn = [this](BasicBlock::iterator ref_inst_itr,

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

@@ -162,9 +162,6 @@ class InstBindlessCheckPass : public InstrumentPass {
   // GenInitCheckCode to every instruction in module.
   Pass::Status ProcessImpl();
 
-  // True if VK_EXT_descriptor_indexing is defined
-  bool ext_descriptor_indexing_defined_;
-
   // Enable instrumentation of runtime array length checking
   bool input_length_enabled_;
 

+ 12 - 10
3rdparty/spirv-tools/source/opt/merge_return_pass.cpp

@@ -81,6 +81,7 @@ bool MergeReturnPass::ProcessStructured(
     return false;
   }
 
+  RecordImmediateDominators(function);
   AddDummyLoopAroundFunction();
 
   std::list<BasicBlock*> order;
@@ -236,10 +237,6 @@ void MergeReturnPass::UpdatePhiNodes(BasicBlock* new_source,
     inst->AddOperand({SPV_OPERAND_TYPE_ID, {new_source->id()}});
     context()->UpdateDefUse(inst);
   });
-
-  // Store the immediate dominator for this block in case new phi nodes will be
-  // needed later.
-  RecordImmediateDominator(target);
 }
 
 void MergeReturnPass::CreatePhiNodesForInst(BasicBlock* merge_block,
@@ -683,7 +680,7 @@ void MergeReturnPass::AddNewPhiNodes(BasicBlock* bb) {
     return;
   }
 
-  BasicBlock* current_bb = new_merge_nodes_[bb];
+  BasicBlock* current_bb = context()->get_instr_block(original_dominator_[bb]);
   while (current_bb != nullptr && current_bb != dominator) {
     for (Instruction& inst : *current_bb) {
       CreatePhiNodesForInst(bb, inst);
@@ -692,11 +689,16 @@ void MergeReturnPass::AddNewPhiNodes(BasicBlock* bb) {
   }
 }
 
-void MergeReturnPass::RecordImmediateDominator(BasicBlock* block) {
-  DominatorAnalysis* dom_tree =
-      context()->GetDominatorAnalysis(block->GetParent());
-  auto idom = dom_tree->ImmediateDominator(block);
-  new_merge_nodes_[block] = idom;
+void MergeReturnPass::RecordImmediateDominators(Function* function) {
+  DominatorAnalysis* dom_tree = context()->GetDominatorAnalysis(function);
+  for (BasicBlock& bb : *function) {
+    BasicBlock* dominator_bb = dom_tree->ImmediateDominator(&bb);
+    if (dominator_bb && dominator_bb != cfg()->pseudo_entry_block()) {
+      original_dominator_[&bb] = dominator_bb->terminator();
+    } else {
+      original_dominator_[&bb] = nullptr;
+    }
+  }
 }
 
 void MergeReturnPass::InsertAfterElement(BasicBlock* element,

+ 13 - 13
3rdparty/spirv-tools/source/opt/merge_return_pass.h

@@ -246,24 +246,23 @@ class MergeReturnPass : public MemPass {
   // instruction.
   void CreatePhiNodesForInst(BasicBlock* merge_block, Instruction& inst);
 
-  // Traverse the nodes in |new_merge_nodes_|, and adds the OpPhi instructions
-  // that are needed to make the code correct.  It is assumed that at this point
-  // there are no unreachable blocks in the control flow graph.
+  // Add new phi nodes for any id that no longer dominate all of it uses.  A phi
+  // node is added to a block |bb| for an id if the id is defined between the
+  // original immediate dominator of |bb| and its new immidiate dominator.  It
+  // is assumed that at this point there are no unreachable blocks in the
+  // control flow graph.
   void AddNewPhiNodes();
 
   // Creates any new phi nodes that are needed in |bb|.  |AddNewPhiNodes| must
   // have already been called on the original dominators of |bb|.
   void AddNewPhiNodes(BasicBlock* bb);
 
-  // Saves |block| to a list of basic block that will require OpPhi nodes to be
-  // added by calling |AddNewPhiNodes|.  It is assumed that |block| used to have
-  // a single predecessor, |single_original_pred|, but now has more.
-  void RecordImmediateDominator(BasicBlock* block);
+  // Records the terminator of immediate dominator for every basic block in
+  // |function|.
+  void RecordImmediateDominators(Function* function);
 
   // Modifies existing OpPhi instruction in |target| block to account for the
-  // new edge from |new_source|.  The value for that edge will be an Undef. If
-  // |target| only had a single predecessor, then it is marked as needing new
-  // phi nodes.  See |RecordImmediateDominator|.
+  // new edge from |new_source|.  The value for that edge will be an Undef.
   //
   // The CFG must not include the edge from |new_source| to |target| yet.
   void UpdatePhiNodes(BasicBlock* new_source, BasicBlock* target);
@@ -317,9 +316,10 @@ class MergeReturnPass : public MemPass {
   // after processing the current function.
   BasicBlock* final_return_block_;
 
-  // This is a map from a node to its original immediate dominator.  This is
-  // used to determine which values will require a new phi node.
-  std::unordered_map<BasicBlock*, BasicBlock*> new_merge_nodes_;
+  // This is a map from a node to its original immediate dominator identified by
+  // the terminator if that block.  We use the terminator because the block we
+  // want may change if the block is split.
+  std::unordered_map<BasicBlock*, Instruction*> original_dominator_;
 
   // A map from a basic block, bb, to the set of basic blocks which represent
   // the new edges that reach |bb|.

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

@@ -102,6 +102,7 @@ void SSARewriter::ReplacePhiUsersWith(const PhiCandidate& phi_to_remove,
                                       uint32_t repl_id) {
   for (uint32_t user_id : phi_to_remove.users()) {
     PhiCandidate* user_phi = GetPhiCandidate(user_id);
+    BasicBlock* bb = pass_->context()->get_instr_block(user_id);
     if (user_phi) {
       // If the user is a Phi candidate, replace all arguments that refer to
       // |phi_to_remove.result_id()| with |repl_id|.
@@ -110,6 +111,10 @@ void SSARewriter::ReplacePhiUsersWith(const PhiCandidate& phi_to_remove,
           arg = repl_id;
         }
       }
+    } else if (bb->id() == user_id) {
+      // The phi candidate is the definition of the variable at basic block
+      // |bb|.  We must change this to the replacement.
+      WriteVariable(phi_to_remove.var_id(), bb, repl_id);
     } else {
       // For regular loads, traverse the |load_replacement_| table looking for
       // instances of |phi_to_remove|.
@@ -259,6 +264,8 @@ uint32_t SSARewriter::GetReachingDef(uint32_t var_id, BasicBlock* bb) {
     // require a Phi instruction.  This will act as |var_id|'s current
     // definition to break potential cycles.
     PhiCandidate& phi_candidate = CreatePhiCandidate(var_id, bb);
+
+    // Set the value for |bb| to avoid an infinite recursion.
     WriteVariable(var_id, bb, phi_candidate.result_id());
     val_id = AddPhiOperands(&phi_candidate);
   }

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

@@ -188,6 +188,9 @@ class SSARewriter {
   // value |val_id|.
   void WriteVariable(uint32_t var_id, BasicBlock* bb, uint32_t val_id) {
     defs_at_block_[bb][var_id] = val_id;
+    if (auto* pc = GetPhiCandidate(val_id)) {
+      pc->AddUser(bb->id());
+    }
   }
 
   // Processes the store operation |inst| in basic block |bb|. This extracts

+ 9 - 6
3rdparty/spirv-tools/source/val/function.cpp

@@ -317,13 +317,10 @@ int Function::GetBlockDepth(BasicBlock* bb) {
   if (!bb_dom || bb == bb_dom) {
     // This block has no dominator, so it's at depth 0.
     block_depth_[bb] = 0;
-  } else if (bb->is_type(kBlockTypeMerge)) {
-    // If this is a merge block, its depth is equal to the block before
-    // branching.
-    BasicBlock* header = merge_block_header_[bb];
-    assert(header);
-    block_depth_[bb] = GetBlockDepth(header);
   } else if (bb->is_type(kBlockTypeContinue)) {
+    // This rule must precede the rule for merge blocks in order to set up
+    // depths correctly. If a block is both a merge and continue then the merge
+    // is nested within the continue's loop (or the graph is incorrect).
     // The depth of the continue block entry point is 1 + loop header depth.
     Construct* continue_construct =
         entry_block_to_construct_[std::make_pair(bb, ConstructType::kContinue)];
@@ -341,6 +338,12 @@ int Function::GetBlockDepth(BasicBlock* bb) {
     } else {
       block_depth_[bb] = 1 + GetBlockDepth(loop_header);
     }
+  } else if (bb->is_type(kBlockTypeMerge)) {
+    // If this is a merge block, its depth is equal to the block before
+    // branching.
+    BasicBlock* header = merge_block_header_[bb];
+    assert(header);
+    block_depth_[bb] = GetBlockDepth(header);
   } else if (bb_dom->is_type(kBlockTypeHeader) ||
              bb_dom->is_type(kBlockTypeLoop)) {
     // The dominator of the given block is a header block. So, the nesting

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

@@ -12,11 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "source/val/validate.h"
-
 #include "source/opcode.h"
 #include "source/spirv_target_env.h"
 #include "source/val/instruction.h"
+#include "source/val/validate.h"
 #include "source/val/validation_state.h"
 
 namespace spvtools {
@@ -287,11 +286,11 @@ spv_result_t ValidateDecorationGroup(ValidationState_t& _,
     auto use = pair.first;
     if (use->opcode() != SpvOpDecorate && use->opcode() != SpvOpGroupDecorate &&
         use->opcode() != SpvOpGroupMemberDecorate &&
-        use->opcode() != SpvOpName) {
+        use->opcode() != SpvOpName && use->opcode() != SpvOpDecorateId) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result id of OpDecorationGroup can only "
              << "be targeted by OpName, OpGroupDecorate, "
-             << "OpDecorate, and OpGroupMemberDecorate";
+             << "OpDecorate, OpDecorateId, and OpGroupMemberDecorate";
     }
   }
   return SPV_SUCCESS;

+ 56 - 24
3rdparty/spirv-tools/source/val/validate_atomics.cpp

@@ -25,6 +25,28 @@
 #include "source/val/validate_scopes.h"
 #include "source/val/validation_state.h"
 
+namespace {
+
+bool IsStorageClassAllowedByUniversalRules(uint32_t storage_class) {
+  switch (storage_class) {
+    case SpvStorageClassUniform:
+    case SpvStorageClassStorageBuffer:
+    case SpvStorageClassWorkgroup:
+    case SpvStorageClassCrossWorkgroup:
+    case SpvStorageClassGeneric:
+    case SpvStorageClassAtomicCounter:
+    case SpvStorageClassImage:
+    case SpvStorageClassFunction:
+    case SpvStorageClassPhysicalStorageBufferEXT:
+      return true;
+      break;
+    default:
+      return false;
+  }
+}
+
+}  // namespace
+
 namespace spvtools {
 namespace val {
 
@@ -119,32 +141,42 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
                << ": expected Pointer to be of type OpTypePointer";
       }
 
-      switch (storage_class) {
-        case SpvStorageClassUniform:
-        case SpvStorageClassWorkgroup:
-        case SpvStorageClassCrossWorkgroup:
-        case SpvStorageClassGeneric:
-        case SpvStorageClassAtomicCounter:
-        case SpvStorageClassImage:
-        case SpvStorageClassStorageBuffer:
-        case SpvStorageClassPhysicalStorageBufferEXT:
-          break;
-        default:
-          if (spvIsOpenCLEnv(_.context()->target_env)) {
-            if (storage_class != SpvStorageClassFunction) {
-              return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                     << spvOpcodeString(opcode)
-                     << ": expected Pointer Storage Class to be Uniform, "
-                        "Workgroup, CrossWorkgroup, Generic, AtomicCounter, "
-                        "Image, StorageBuffer or Function";
-            }
-          } else {
+      // Validate storage class against universal rules
+      if (!IsStorageClassAllowedByUniversalRules(storage_class)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << spvOpcodeString(opcode)
+               << ": storage class forbidden by universal validation rules.";
+      }
+
+      // Then Shader rules
+      if (_.HasCapability(SpvCapabilityShader)) {
+        if (storage_class == SpvStorageClassFunction) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << spvOpcodeString(opcode)
+                 << ": Function storage class forbidden when the Shader "
+                    "capability is declared.";
+        }
+      }
+
+      // And finally OpenCL environment rules
+      if (spvIsOpenCLEnv(_.context()->target_env)) {
+        if ((storage_class != SpvStorageClassFunction) &&
+            (storage_class != SpvStorageClassWorkgroup) &&
+            (storage_class != SpvStorageClassCrossWorkgroup) &&
+            (storage_class != SpvStorageClassGeneric)) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << spvOpcodeString(opcode)
+                 << ": storage class must be Function, Workgroup, "
+                    "CrossWorkGroup or Generic in the OpenCL environment.";
+        }
+
+        if (_.context()->target_env == SPV_ENV_OPENCL_1_2) {
+          if (storage_class == SpvStorageClassGeneric) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                   << spvOpcodeString(opcode)
-                   << ": expected Pointer Storage Class to be Uniform, "
-                      "Workgroup, CrossWorkgroup, Generic, AtomicCounter, "
-                      "Image or StorageBuffer";
+                   << "Storage class cannot be Generic in OpenCL 1.2 "
+                      "environment";
           }
+        }
       }
 
       if (opcode == SpvOpAtomicFlagTestAndSet ||

+ 39 - 26
3rdparty/spirv-tools/source/val/validate_cfg.cpp

@@ -493,41 +493,54 @@ spv_result_t StructuredSwitchChecks(ValidationState_t& _, Function* function,
   std::map<uint32_t, uint32_t> num_fall_through_targeted;
   uint32_t default_case_fall_through = 0u;
   uint32_t default_target = switch_inst->GetOperandAs<uint32_t>(1u);
-  std::unordered_set<uint32_t> seen;
+  bool default_appears_multiple_times = false;
+  for (uint32_t i = 3; i < switch_inst->operands().size(); i += 2) {
+    if (default_target == switch_inst->GetOperandAs<uint32_t>(i)) {
+      default_appears_multiple_times = true;
+      break;
+    }
+  }
+  std::unordered_map<uint32_t, uint32_t> seen_to_fall_through;
   for (uint32_t i = 1; i < switch_inst->operands().size(); i += 2) {
     uint32_t target = switch_inst->GetOperandAs<uint32_t>(i);
     if (target == merge->id()) continue;
 
-    if (!seen.insert(target).second) continue;
-
-    const auto target_block = function->GetBlock(target).first;
-    // OpSwitch must dominate all its case constructs.
-    if (header->reachable() && target_block->reachable() &&
-        !header->dominates(*target_block)) {
-      return _.diag(SPV_ERROR_INVALID_CFG, header->label())
-             << "Selection header " << _.getIdName(header->id())
-             << " does not dominate its case construct " << _.getIdName(target);
-    }
-
     uint32_t case_fall_through = 0u;
-    if (auto error = FindCaseFallThrough(_, target_block, &case_fall_through,
-                                         merge, case_targets, function)) {
-      return error;
-    }
+    auto seen_iter = seen_to_fall_through.find(target);
+    if (seen_iter == seen_to_fall_through.end()) {
+      const auto target_block = function->GetBlock(target).first;
+      // OpSwitch must dominate all its case constructs.
+      if (header->reachable() && target_block->reachable() &&
+          !header->dominates(*target_block)) {
+        return _.diag(SPV_ERROR_INVALID_CFG, header->label())
+               << "Selection header " << _.getIdName(header->id())
+               << " does not dominate its case construct "
+               << _.getIdName(target);
+      }
 
-    // Track how many time the fall through case has been targeted.
-    if (case_fall_through != 0u) {
-      auto where = num_fall_through_targeted.lower_bound(case_fall_through);
-      if (where == num_fall_through_targeted.end() ||
-          where->first != case_fall_through) {
-        num_fall_through_targeted.insert(where,
-                                         std::make_pair(case_fall_through, 1));
-      } else {
-        where->second++;
+      if (auto error = FindCaseFallThrough(_, target_block, &case_fall_through,
+                                           merge, case_targets, function)) {
+        return error;
       }
+
+      // Track how many time the fall through case has been targeted.
+      if (case_fall_through != 0u) {
+        auto where = num_fall_through_targeted.lower_bound(case_fall_through);
+        if (where == num_fall_through_targeted.end() ||
+            where->first != case_fall_through) {
+          num_fall_through_targeted.insert(
+              where, std::make_pair(case_fall_through, 1));
+        } else {
+          where->second++;
+        }
+      }
+      seen_to_fall_through.insert(std::make_pair(target, case_fall_through));
+    } else {
+      case_fall_through = seen_iter->second;
     }
 
-    if (case_fall_through == default_target) {
+    if (case_fall_through == default_target &&
+        !default_appears_multiple_times) {
       case_fall_through = default_case_fall_through;
     }
     if (case_fall_through != 0u) {

+ 38 - 30
3rdparty/spirv-tools/source/val/validate_derivatives.cpp

@@ -53,37 +53,45 @@ spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst) {
                << "Expected P type and Result Type to be the same: "
                << spvOpcodeString(opcode);
       }
-
-      const spvtools::Extension compute_shader_derivatives_extension =
-          kSPV_NV_compute_shader_derivatives;
-      ExtensionSet exts(1, &compute_shader_derivatives_extension);
-
-      if (_.HasAnyOfExtensions(exts)) {
-        _.function(inst->function()->id())
-            ->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
-                                                        std::string* message) {
-              if (model != SpvExecutionModelFragment &&
-                  model != SpvExecutionModelGLCompute) {
-                if (message) {
-                  *message =
-                      std::string(
-                          "Derivative instructions require Fragment execution "
-                          "model: ") +
-                      spvOpcodeString(opcode);
-                }
-                return false;
+      _.function(inst->function()->id())
+          ->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
+                                                      std::string* message) {
+            if (model != SpvExecutionModelFragment &&
+                model != SpvExecutionModelGLCompute) {
+              if (message) {
+                *message =
+                    std::string(
+                        "Derivative instructions require Fragment or GLCompute "
+                        "execution model: ") +
+                    spvOpcodeString(opcode);
               }
-              return true;
-            });
-      } else {
-        _.function(inst->function()->id())
-            ->RegisterExecutionModelLimitation(
-                SpvExecutionModelFragment,
-                std::string(
-                    "Derivative instructions require Fragment execution "
-                    "model: ") +
-                    spvOpcodeString(opcode));
-      }
+              return false;
+            }
+            return true;
+          });
+      _.function(inst->function()->id())
+          ->RegisterLimitation([opcode](const ValidationState_t& state,
+                                        const Function* entry_point,
+                                        std::string* message) {
+            const auto* models = state.GetExecutionModels(entry_point->id());
+            const auto* modes = state.GetExecutionModes(entry_point->id());
+            if (models->find(SpvExecutionModelGLCompute) != models->end() &&
+                modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+                    modes->end() &&
+                modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+                    modes->end()) {
+              if (message) {
+                *message = std::string(
+                               "Derivative instructions require "
+                               "DerivativeGroupQuadsNV "
+                               "or DerivativeGroupLinearNV execution mode for "
+                               "GLCompute execution model: ") +
+                           spvOpcodeString(opcode);
+              }
+              return false;
+            }
+            return true;
+          });
       break;
     }
 

+ 71 - 5
3rdparty/spirv-tools/source/val/validate_image.cpp

@@ -1710,8 +1710,39 @@ spv_result_t ValidateImageQueryLod(ValidationState_t& _,
                                    const Instruction* inst) {
   _.function(inst->function()->id())
       ->RegisterExecutionModelLimitation(
-          SpvExecutionModelFragment,
-          "OpImageQueryLod requires Fragment execution model");
+          [&](SpvExecutionModel model, std::string* message) {
+            if (model != SpvExecutionModelFragment &&
+                model != SpvExecutionModelGLCompute) {
+              if (message) {
+                *message = std::string(
+                    "OpImageQueryLod requires Fragment or GLCompute execution "
+                    "model");
+              }
+              return false;
+            }
+            return true;
+          });
+  _.function(inst->function()->id())
+      ->RegisterLimitation([](const ValidationState_t& state,
+                              const Function* entry_point,
+                              std::string* message) {
+        const auto* models = state.GetExecutionModels(entry_point->id());
+        const auto* modes = state.GetExecutionModes(entry_point->id());
+        if (models->find(SpvExecutionModelGLCompute) != models->end() &&
+            modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+                modes->end() &&
+            modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+                modes->end()) {
+          if (message) {
+            *message = std::string(
+                "OpImageQueryLod requires DerivativeGroupQuadsNV "
+                "or DerivativeGroupLinearNV execution mode for GLCompute "
+                "execution model");
+          }
+          return false;
+        }
+        return true;
+      });
 
   const uint32_t result_type = inst->type_id();
   if (!_.IsFloatVectorType(result_type)) {
@@ -1835,9 +1866,44 @@ spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) {
   const SpvOp opcode = inst->opcode();
   if (IsImplicitLod(opcode)) {
     _.function(inst->function()->id())
-        ->RegisterExecutionModelLimitation(
-            SpvExecutionModelFragment,
-            "ImplicitLod instructions require Fragment execution model");
+        ->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
+                                                    std::string* message) {
+          if (model != SpvExecutionModelFragment &&
+              model != SpvExecutionModelGLCompute) {
+            if (message) {
+              *message =
+                  std::string(
+                      "ImplicitLod instructions require Fragment or GLCompute "
+                      "execution model: ") +
+                  spvOpcodeString(opcode);
+            }
+            return false;
+          }
+          return true;
+        });
+    _.function(inst->function()->id())
+        ->RegisterLimitation([opcode](const ValidationState_t& state,
+                                      const Function* entry_point,
+                                      std::string* message) {
+          const auto* models = state.GetExecutionModels(entry_point->id());
+          const auto* modes = state.GetExecutionModes(entry_point->id());
+          if (models->find(SpvExecutionModelGLCompute) != models->end() &&
+              modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+                  modes->end() &&
+              modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+                  modes->end()) {
+            if (message) {
+              *message =
+                  std::string(
+                      "ImplicitLod instructions require DerivativeGroupQuadsNV "
+                      "or DerivativeGroupLinearNV execution mode for GLCompute "
+                      "execution model: ") +
+                  spvOpcodeString(opcode);
+            }
+            return false;
+          }
+          return true;
+        });
   }
 
   switch (opcode) {

+ 56 - 0
3rdparty/spirv-tools/test/opt/aggressive_dead_code_elim_test.cpp

@@ -6560,6 +6560,62 @@ OpFunctionEnd
   SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
 }
 
+TEST_F(AggressiveDCETest, LiveDecorateId) {
+  const std::string spirv = R"(OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %1 "main" %2
+OpExecutionMode %1 LocalSize 8 1 1
+OpDecorate %2 DescriptorSet 0
+OpDecorate %2 Binding 0
+OpDecorateId %3 UniformId %uint_2
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%uint_2 = OpConstant %uint 2
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
+%8 = OpTypeFunction %void
+%1 = OpFunction %void None %8
+%9 = OpLabel
+%3 = OpLoad %uint %2
+OpStore %2 %3
+OpReturn
+OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
+  OptimizerOptions()->preserve_spec_constants_ = true;
+  SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
+}
+
+TEST_F(AggressiveDCETest, LiveDecorateIdOnGroup) {
+  const std::string spirv = R"(OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %1 "main" %2
+OpExecutionMode %1 LocalSize 8 1 1
+OpDecorate %2 DescriptorSet 0
+OpDecorate %2 Binding 0
+OpDecorateId %3 UniformId %uint_2
+%3 = OpDecorationGroup
+OpGroupDecorate %3 %5
+%void = OpTypeVoid
+%uint = OpTypeInt 32 0
+%uint_2 = OpConstant %uint 2
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
+%9 = OpTypeFunction %void
+%1 = OpFunction %void None %9
+%10 = OpLabel
+%5 = OpLoad %uint %2
+OpStore %2 %5
+OpReturn
+OpFunctionEnd
+)";
+
+  SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
+  OptimizerOptions()->preserve_spec_constants_ = true;
+  SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    Check that logical addressing required

+ 30 - 28
3rdparty/spirv-tools/test/opt/inst_bindless_check_test.cpp

@@ -255,7 +255,7 @@ OpFunctionEnd
           func_pt2_before,
       entry_after + names_annots + new_annots + consts_types_vars +
           new_consts_types_vars + func_pt1 + func_pt2_after + output_func,
-      true, true);
+      true, true, 7u, 23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, NoInstrumentConstIndexInbounds) {
@@ -335,7 +335,8 @@ OpFunctionEnd
 )";
 
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndCheck<InstBindlessCheckPass>(before, before, true, true);
+  SinglePassRunAndCheck<InstBindlessCheckPass>(before, before, true, true, 7u,
+                                               23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, InstrumentMultipleInstructions) {
@@ -630,7 +631,7 @@ OpFunctionEnd
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true);
+      true, 7u, 23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, InstrumentOpImage) {
@@ -858,7 +859,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true);
+      true, 7u, 23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, InstrumentSampledImage) {
@@ -1081,7 +1082,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true);
+      true, 7u, 23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, InstrumentImageWrite) {
@@ -1306,7 +1307,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true);
+      true, 7u, 23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, InstrumentVertexSimple) {
@@ -1580,7 +1581,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true);
+      true, 7u, 23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, MultipleDebugFunctions) {
@@ -1903,7 +1904,8 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func1_before + func2_before,
-      defs_after + func1_after + func2_after + output_func, true, true);
+      defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u,
+      false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, RuntimeArray) {
@@ -2276,18 +2278,19 @@ OpFunctionEnd
 
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(whole_file, whole_file, true,
-                                               true);
+                                               true, 7u, 23u, false, false, 1u);
 }
 
 TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptor) {
   // This test verifies that the pass will correctly instrument vanilla
   // texture sample on a scalar descriptor with an initialization check if the
-  // SPV_EXT_descriptor_checking extension is enabled. This is the same shader
-  // as NoInstrumentNonBindless, but with the extension hacked on in the SPIR-V.
+  // input_init_enable argument is set to true. This can happen when the
+  // descriptor indexing extension is enabled in the API but the SPIR-V
+  // does not have the extension enabled because it does not contain a
+  // runtime array. This is the same shader as NoInstrumentNonBindless.
 
   const std::string defs_before =
       R"(OpCapability Shader
-OpExtension "SPV_EXT_descriptor_indexing"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
@@ -2324,7 +2327,6 @@ OpDecorate %_entryPointOutput_vColor Location 0
 
   const std::string defs_after =
       R"(OpCapability Shader
-OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -2395,7 +2397,7 @@ OpDecorate %gl_FragCoord BuiltIn FragCoord
 %uint_6 = OpConstant %uint 6
 %uint_7 = OpConstant %uint 7
 %uint_8 = OpConstant %uint 8
-%uint_40 = OpConstant %uint 40
+%uint_39 = OpConstant %uint 39
 %113 = OpConstantNull %v4float
 )";
 
@@ -2429,7 +2431,7 @@ OpBranchConditional %52 %55 %56
 %59 = OpImageSampleImplicitLod %v4float %58 %20
 OpBranch %54
 %56 = OpLabel
-%112 = OpFunctionCall %void %60 %uint_40 %uint_1 %uint_0 %uint_0
+%112 = OpFunctionCall %void %60 %uint_39 %uint_1 %uint_0 %uint_0
 OpBranch %54
 %54 = OpLabel
 %114 = OpPhi %v4float %59 %55 %113 %56
@@ -4456,7 +4458,7 @@ OpFunctionEnd
           func_pt2_before,
       entry_after + names_annots + new_annots + consts_types_vars +
           new_consts_types_vars + func_pt1 + func_pt2_after + output_func,
-      true, true, 7u, 23u, true, true, 2u);
+      true, true, 7u, 23u, false, false, 2u);
 }
 
 TEST_F(InstBindlessTest, InstrumentMultipleInstructionsV2) {
@@ -4751,7 +4753,7 @@ OpFunctionEnd
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, true, true, 2u);
+      true, 7u, 23u, false, false, 2u);
 }
 
 TEST_F(InstBindlessTest, InstrumentOpImageV2) {
@@ -4979,7 +4981,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, true, true, 2u);
+      true, 7u, 23u, false, false, 2u);
 }
 
 TEST_F(InstBindlessTest, InstrumentSampledImageV2) {
@@ -5202,7 +5204,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, true, true, 2u);
+      true, 7u, 23u, false, false, 2u);
 }
 
 TEST_F(InstBindlessTest, InstrumentImageWriteV2) {
@@ -5427,7 +5429,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, true, true, 2u);
+      true, 7u, 23u, false, false, 2u);
 }
 
 TEST_F(InstBindlessTest, InstrumentVertexSimpleV2) {
@@ -5701,7 +5703,7 @@ OpFunctionEnd
   // SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func_before, defs_after + func_after + output_func, true,
-      true, 7u, 23u, true, true, 2u);
+      true, 7u, 23u, false, false, 2u);
 }
 
 TEST_F(InstBindlessTest, MultipleDebugFunctionsV2) {
@@ -6025,7 +6027,7 @@ OpFunctionEnd
   SinglePassRunAndCheck<InstBindlessCheckPass>(
       defs_before + func1_before + func2_before,
       defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u,
-      true, true, 2u);
+      false, false, 2u);
 }
 
 TEST_F(InstBindlessTest, RuntimeArrayV2) {
@@ -6327,12 +6329,13 @@ OpFunctionEnd
 TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptorV2) {
   // This test verifies that the pass will correctly instrument vanilla
   // texture sample on a scalar descriptor with an initialization check if the
-  // SPV_EXT_descriptor_checking extension is enabled. This is the same shader
-  // as NoInstrumentNonBindless, but with the extension hacked on in the SPIR-V.
+  // input_init_enable argument is set to true. This can happen when the
+  // descriptor indexing extension is enabled in the API but the SPIR-V
+  // does not have the extension enabled because it does not contain a
+  // runtime array. This is the same shader as NoInstrumentNonBindless.
 
   const std::string defs_before =
       R"(OpCapability Shader
-OpExtension "SPV_EXT_descriptor_indexing"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
@@ -6369,7 +6372,6 @@ OpDecorate %_entryPointOutput_vColor Location 0
 
   const std::string defs_after =
       R"(OpCapability Shader
-OpExtension "SPV_EXT_descriptor_indexing"
 OpExtension "SPV_KHR_storage_buffer_storage_class"
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
@@ -6440,7 +6442,7 @@ OpDecorate %gl_FragCoord BuiltIn FragCoord
 %uint_7 = OpConstant %uint 7
 %uint_8 = OpConstant %uint 8
 %uint_9 = OpConstant %uint 9
-%uint_40 = OpConstant %uint 40
+%uint_39 = OpConstant %uint 39
 %113 = OpConstantNull %v4float
 )";
 
@@ -6474,7 +6476,7 @@ OpBranchConditional %52 %55 %56
 %59 = OpImageSampleImplicitLod %v4float %58 %20
 OpBranch %54
 %56 = OpLabel
-%112 = OpFunctionCall %void %60 %uint_40 %uint_1 %uint_0 %uint_0
+%112 = OpFunctionCall %void %60 %uint_39 %uint_1 %uint_0 %uint_0
 OpBranch %54
 %54 = OpLabel
 %114 = OpPhi %v4float %59 %55 %113 %56

+ 57 - 0
3rdparty/spirv-tools/test/opt/local_ssa_elim_test.cpp

@@ -1930,6 +1930,63 @@ TEST_F(LocalSSAElimTest, VariablePointerTest2) {
   SinglePassRunAndMatch<LocalMultiStoreElimPass>(text, false);
 }
 
+TEST_F(LocalSSAElimTest, ChainedTrivialPhis) {
+  // Check that the copy object get the undef value implicitly assigned in the
+  // entry block.
+  const std::string text = R"(
+; CHECK: [[undef:%\w+]] = OpUndef %v4float
+; CHECK: OpCopyObject %v4float [[undef]]
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint GLCompute %2 "main"
+               OpExecutionMode %2 LocalSize 1 18 6
+               OpSource ESSL 310
+       %void = OpTypeVoid
+          %4 = OpTypeFunction %void
+       %bool = OpTypeBool
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+          %2 = OpFunction %void None %4
+          %9 = OpLabel
+         %10 = OpVariable %_ptr_Function_v4float Function
+               OpBranch %11
+         %11 = OpLabel
+               OpLoopMerge %12 %13 None
+               OpBranch %14
+         %14 = OpLabel
+         %15 = OpUndef %bool
+               OpBranchConditional %15 %16 %12
+         %16 = OpLabel
+         %17 = OpUndef %bool
+               OpSelectionMerge %18 None
+               OpBranchConditional %17 %19 %18
+         %19 = OpLabel
+         %20 = OpUndef %bool
+               OpLoopMerge %21 %22 None
+               OpBranchConditional %20 %23 %21
+         %23 = OpLabel
+         %24 = OpLoad %v4float %10
+         %25 = OpCopyObject %v4float %24
+         %26 = OpUndef %bool
+               OpBranch %22
+         %22 = OpLabel
+               OpBranch %19
+         %21 = OpLabel
+               OpBranch %12
+         %18 = OpLabel
+               OpBranch %13
+         %13 = OpLabel
+               OpBranch %11
+         %12 = OpLabel
+         %27 = OpLoad %v4float %10
+               OpReturn
+               OpFunctionEnd
+  )";
+  SinglePassRunAndMatch<SSARewritePass>(text, false);
+}
+
 // TODO(greg-lunarg): Add tests to verify handling of these cases:
 //
 //    No optimization in the presence of

+ 51 - 0
3rdparty/spirv-tools/test/opt/pass_merge_return_test.cpp

@@ -1779,6 +1779,57 @@ TEST_F(MergeReturnPassTest, MergeToMergeBranch) {
   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   SinglePassRunAndMatch<MergeReturnPass>(text, true);
 }
+TEST_F(MergeReturnPassTest, PhiInSecondMerge) {
+  //  Add and use a phi in the second merge block from the return.
+  const std::string text =
+      R"(
+; CHECK: OpLoopMerge
+; CHECK: OpLoopMerge [[merge_bb:%\w+]] [[continue_bb:%\w+]]
+; CHECK: [[continue_bb]] = OpLabel
+; CHECK-NEXT: [[val:%\w+]] = OpUndef %float
+; CHECK: [[merge_bb]] = OpLabel
+; CHECK-NEXT: [[phi:%\w+]] = OpPhi %float {{%\w+}} {{%\w+}} [[val]] [[continue_bb]]
+; CHECK-NOT: OpLabel
+; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} [[old_merge:%\w+]]
+; CHECK: [[old_merge]] = OpLabel
+; CHECK-NEXT: OpConvertFToS %int [[phi]]
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main"
+               OpExecutionMode %2 OriginUpperLeft
+               OpSource ESSL 310
+       %void = OpTypeVoid
+          %4 = OpTypeFunction %void
+        %int = OpTypeInt 32 1
+      %float = OpTypeFloat 32
+       %bool = OpTypeBool
+          %8 = OpUndef %bool
+          %2 = OpFunction %void None %4
+          %9 = OpLabel
+               OpBranch %10
+         %10 = OpLabel
+               OpLoopMerge %11 %12 None
+               OpBranch %13
+         %13 = OpLabel
+               OpLoopMerge %12 %14 None
+               OpBranchConditional %8 %15 %12
+         %15 = OpLabel
+               OpReturn
+         %14 = OpLabel
+               OpBranch %13
+         %12 = OpLabel
+         %16 = OpUndef %float
+               OpBranchConditional %8 %10 %11
+         %11 = OpLabel
+         %17 = OpConvertFToS %int %16
+               OpReturn
+               OpFunctionEnd
+)";
+
+  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  SinglePassRunAndMatch<MergeReturnPass>(text, true);
+}
 
 }  // namespace
 }  // namespace opt

+ 0 - 2
3rdparty/spirv-tools/test/scripts/test_compact_ids.py

@@ -14,8 +14,6 @@
 # limitations under the License.
 """Tests correctness of opt pass tools/opt --compact-ids."""
 
-from __future__ import print_function
-
 import os.path
 import sys
 import tempfile

+ 0 - 2
3rdparty/spirv-tools/test/tools/spirv_test_framework.py

@@ -44,8 +44,6 @@ If --leave-output was not specified, all temporary files and directories will
 be deleted.
 """
 
-from __future__ import print_function
-
 import argparse
 import fnmatch
 import inspect

+ 27 - 21
3rdparty/spirv-tools/test/val/val_atomics_test.cpp

@@ -190,6 +190,9 @@ OpMemoryModel Physical32 OpenCL
 %f32_ptr_uniformconstant = OpTypePointer UniformConstant %f32
 %f32_uc_var = OpVariable %f32_ptr_uniformconstant UniformConstant
 
+%f32_ptr_image = OpTypePointer Image %f32
+%f32_im_var = OpVariable %f32_ptr_image Image
+
 %main = OpFunction %void None %func
 %main_entry = OpLabel
 )";
@@ -288,11 +291,9 @@ OpAtomicStore %f32_var_function %device %relaxed %f32_1
 
   CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("AtomicStore: expected Pointer Storage Class to be Uniform, "
-                "Workgroup, CrossWorkgroup, Generic, AtomicCounter, Image or "
-                "StorageBuffer"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("AtomicStore: Function storage class forbidden when "
+                        "the Shader capability is declared."));
 }
 
 // TODO([email protected]): the corresponding check fails Vulkan CTS,
@@ -500,8 +501,7 @@ TEST_F(ValidateAtomics, AtomicLoadWrongScopeType) {
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("AtomicLoad: expected Memory Scope to be a 32-bit int\n  %40 = "
-                "OpAtomicLoad %float %28 %float_1 %uint_0_1\n"));
+      HasSubstr("AtomicLoad: expected Memory Scope to be a 32-bit int"));
 }
 
 TEST_F(ValidateAtomics, AtomicLoadWrongMemorySemanticsType) {
@@ -641,6 +641,19 @@ OpAtomicStore %f32vec4_var %device %relaxed %f32_1
                 "type"));
 }
 
+TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageTypeForOpenCL) {
+  const std::string body = R"(
+OpAtomicStore %f32_im_var %device %relaxed %f32_1
+)";
+
+  CompileSuccessfully(GenerateKernelCode(body));
+  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("AtomicStore: storage class must be Function, Workgroup, "
+                "CrossWorkGroup or Generic in the OpenCL environment."));
+}
+
 TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageType) {
   const std::string body = R"(
 OpAtomicStore %f32_uc_var %device %relaxed %f32_1
@@ -648,11 +661,9 @@ OpAtomicStore %f32_uc_var %device %relaxed %f32_1
 
   CompileSuccessfully(GenerateKernelCode(body));
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr("AtomicStore: expected Pointer Storage Class to be Uniform, "
-                "Workgroup, CrossWorkgroup, Generic, AtomicCounter, Image or "
-                "StorageBuffer"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("AtomicStore: storage class forbidden by universal "
+                        "validation rules."));
 }
 
 TEST_F(ValidateAtomics, AtomicStoreWrongScopeType) {
@@ -778,9 +789,7 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr(
-          "AtomicExchange: expected Memory Scope to be a 32-bit int\n  %40 = "
-          "OpAtomicExchange %float %28 %float_1 %uint_0_1 %float_0\n"));
+      HasSubstr("AtomicExchange: expected Memory Scope to be a 32-bit int"));
 }
 
 TEST_F(ValidateAtomics, AtomicExchangeWrongMemorySemanticsType) {
@@ -895,8 +904,7 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr("AtomicCompareExchange: expected Memory Scope to be a 32-bit "
-                "int\n  %40 = OpAtomicCompareExchange %float %28 %float_1 "
-                "%uint_0_1 %uint_0_1 %float_0 %float_0\n"));
+                "int"));
 }
 
 TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType1) {
@@ -1077,8 +1085,7 @@ TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongScopeType) {
   EXPECT_THAT(
       getDiagnosticString(),
       HasSubstr(
-          "AtomicFlagTestAndSet: expected Memory Scope to be a 32-bit int\n  "
-          "%40 = OpAtomicFlagTestAndSet %bool %30 %ulong_1 %uint_0_1\n"));
+          "AtomicFlagTestAndSet: expected Memory Scope to be a 32-bit int"));
 }
 
 TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongMemorySemanticsType) {
@@ -1179,8 +1186,7 @@ OpAtomicStore %u32_var %device %relaxed %u32_1
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("AtomicIIncrement: Memory Semantics can have at most "
                         "one of the following bits set: Acquire, Release, "
-                        "AcquireRelease or SequentiallyConsistent\n  %40 = "
-                        "OpAtomicIIncrement %uint %30 %uint_1_0 %uint_6\n"));
+                        "AcquireRelease or SequentiallyConsistent"));
 }
 
 TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsShader) {

+ 174 - 0
3rdparty/spirv-tools/test/val/val_cfg_test.cpp

@@ -2623,6 +2623,134 @@ OpFunctionEnd
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
+TEST_F(ValidateCFG, SwitchCaseOrderingBad1) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+OpName %default "default"
+OpName %other "other"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%undef = OpUndef %int
+%void_fn = OpTypeFunction %void
+%func = OpFunction %void None %void_fn
+%entry = OpLabel
+OpSelectionMerge %merge None
+OpSwitch %undef %default 0 %other 1 %default
+%default = OpLabel
+OpBranch %other
+%other = OpLabel
+OpBranch %merge
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Case construct that targets 1[%default] has branches to the "
+                "case construct that targets 2[%other], but does not "
+                "immediately precede it in the OpSwitch's target list"));
+}
+
+TEST_F(ValidateCFG, SwitchCaseOrderingBad2) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+OpName %default "default"
+OpName %other "other"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%undef = OpUndef %int
+%void_fn = OpTypeFunction %void
+%func = OpFunction %void None %void_fn
+%entry = OpLabel
+OpSelectionMerge %merge None
+OpSwitch %undef %default 0 %default 1 %other
+%other = OpLabel
+OpBranch %default
+%default = OpLabel
+OpBranch %merge
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr("Case construct that targets 2[%other] has branches to the "
+                "case construct that targets 1[%default], but does not "
+                "immediately precede it in the OpSwitch's target list"));
+}
+
+TEST_F(ValidateCFG, SwitchMultipleDefaultWithFallThroughGood) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+OpName %first "first"
+OpName %second "second"
+OpName %third "third"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%undef = OpUndef %int
+%void_fn = OpTypeFunction %void
+%func = OpFunction %void None %void_fn
+%entry = OpLabel
+OpSelectionMerge %merge None
+OpSwitch %undef %second 0 %first 1 %second 2 %third
+%first = OpLabel
+OpBranch %second
+%second = OpLabel
+OpBranch %third
+%third = OpLabel
+OpBranch %merge
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateCFG, SwitchMultipleDefaultWithFallThroughBad) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+OpName %first "first"
+OpName %second "second"
+OpName %third "third"
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%undef = OpUndef %int
+%void_fn = OpTypeFunction %void
+%func = OpFunction %void None %void_fn
+%entry = OpLabel
+OpSelectionMerge %merge None
+OpSwitch %undef %second 0 %second 1 %first 2 %third
+%first = OpLabel
+OpBranch %second
+%second = OpLabel
+OpBranch %third
+%third = OpLabel
+OpBranch %merge
+%merge = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
+}
+
 TEST_F(ValidateCFG, GoodUnreachableSelection) {
   const std::string text = R"(
 OpCapability Shader
@@ -3575,6 +3703,52 @@ OpFunctionEnd
                         "10[%10], but not via a structured exit"));
 }
 
+TEST_F(ValidateCFG, ContinueFromNestedSelection) {
+  const std::string text = R"(
+OpCapability Shader
+OpCapability Linkage
+OpMemoryModel Logical GLSL450
+%void = OpTypeVoid
+%void_fn = OpTypeFunction %void
+%bool = OpTypeBool
+%undef = OpUndef %bool
+%4 = OpFunction %void None %void_fn
+%5 = OpLabel
+OpBranch %48
+%48 = OpLabel
+OpLoopMerge %47 %50 None
+OpBranch %10
+%10 = OpLabel
+OpLoopMerge %12 %37 None
+OpBranchConditional %undef %11 %12
+%11 = OpLabel
+OpSelectionMerge %31 None
+OpBranchConditional %undef %30 %31
+%30 = OpLabel
+OpSelectionMerge %37 None
+OpBranchConditional %undef %36 %37
+%36 = OpLabel
+OpBranch %37
+%37 = OpLabel
+OpBranch %10
+%31 = OpLabel
+OpBranch %12
+%12 = OpLabel
+OpSelectionMerge %55 None
+OpBranchConditional %undef %47 %55
+%55 = OpLabel
+OpBranch %47
+%50 = OpLabel
+OpBranch %48
+%47 = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(text);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
 /// TODO(umar): Nested CFG constructs
 
 }  // namespace

+ 3 - 4
3rdparty/spirv-tools/test/val/val_derivatives_test.cpp

@@ -145,10 +145,9 @@ TEST_F(ValidateDerivatives, OpDPdxWrongExecutionModel) {
 
   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(
-      getDiagnosticString(),
-      HasSubstr(
-          "Derivative instructions require Fragment execution model: DPdx"));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("Derivative instructions require Fragment or GLCompute "
+                        "execution model: DPdx"));
 }
 
 }  // namespace

+ 1 - 1
3rdparty/spirv-tools/test/val/val_id_test.cpp

@@ -314,7 +314,7 @@ TEST_F(ValidateIdWithMessage, OpDecorationGroupBad) {
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Result id of OpDecorationGroup can only "
                         "be targeted by OpName, OpGroupDecorate, "
-                        "OpDecorate, and OpGroupMemberDecorate"));
+                        "OpDecorate, OpDecorateId, and OpGroupMemberDecorate"));
 }
 TEST_F(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) {
   std::string spirv = R"(

+ 141 - 44
3rdparty/spirv-tools/test/val/val_image_test.cpp

@@ -35,6 +35,7 @@ std::string GenerateShaderCode(
     const std::string& body,
     const std::string& capabilities_and_extensions = "",
     const std::string& execution_model = "Fragment",
+    const std::string& execution_mode = "",
     const spv_target_env env = SPV_ENV_UNIVERSAL_1_0,
     const std::string& memory_model = "GLSL450") {
   std::ostringstream ss;
@@ -85,6 +86,7 @@ OpCapability ImageBuffer
   if (execution_model == "Fragment") {
     ss << "OpExecutionMode %main OriginUpperLeft\n";
   }
+  ss << execution_mode;
 
   if (env == SPV_ENV_VULKAN_1_0) {
     ss << R"(
@@ -606,7 +608,7 @@ TEST_F(ValidateImage, SampledImageVulkanSuccess) {
 )";
 
   const spv_target_env env = SPV_ENV_VULKAN_1_0;
-  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env), env);
+  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
 }
 
@@ -658,7 +660,7 @@ TEST_F(ValidateImage, SampledImageVulkanUnknownSampled) {
 )";
 
   const spv_target_env env = SPV_ENV_VULKAN_1_0;
-  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env), env);
+  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("Expected Image 'Sampled' parameter to "
@@ -847,7 +849,7 @@ TEST_F(ValidateImage, SampleImplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -967,7 +969,7 @@ TEST_F(ValidateImage, SampleExplicitLodSuccessShader) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1552,7 +1554,7 @@ TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1686,7 +1688,7 @@ TEST_F(ValidateImage, SampleProjImplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1807,7 +1809,7 @@ TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -1930,7 +1932,7 @@ TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -2054,7 +2056,7 @@ TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -2177,7 +2179,7 @@ TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -2280,7 +2282,7 @@ TEST_F(ValidateImage, FetchSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -2439,7 +2441,7 @@ TEST_F(ValidateImage, GatherSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -2695,7 +2697,7 @@ TEST_F(ValidateImage, DrefGatherSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -2790,7 +2792,7 @@ TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) {
 )";
 
   spv_target_env env = SPV_ENV_VULKAN_1_0;
-  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env).c_str(),
+  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
                       env);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
   EXPECT_THAT(getDiagnosticString(),
@@ -3008,7 +3010,7 @@ TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) {
 )";
 
   spv_target_env env = SPV_ENV_VULKAN_1_0;
-  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env).c_str(),
+  CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
                       env);
   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
   EXPECT_THAT(
@@ -3710,8 +3712,10 @@ TEST_F(ValidateImage, QueryLodWrongExecutionModel) {
 
   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpImageQueryLod requires Fragment execution model"));
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpImageQueryLod requires Fragment or GLCompute execution model"));
 }
 
 TEST_F(ValidateImage, QueryLodWrongExecutionModelWithFunc) {
@@ -3729,8 +3733,55 @@ OpFunctionEnd
 
   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(
+      getDiagnosticString(),
+      HasSubstr(
+          "OpImageQueryLod requires Fragment or GLCompute execution model"));
+}
+
+TEST_F(ValidateImage, QueryLodComputeShaderDerivatives) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
+)";
+
+  const std::string extra = R"(
+OpCapability ComputeDerivativeGroupLinearNV
+OpExtension "SPV_NV_compute_shader_derivatives"
+)";
+  const std::string mode = R"(
+OpExecutionMode %main LocalSize 8 8 1
+OpExecutionMode %main DerivativeGroupLinearNV
+)";
+  CompileSuccessfully(
+      GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
+)";
+
+  const std::string extra = R"(
+OpCapability ComputeDerivativeGroupLinearNV
+OpExtension "SPV_NV_compute_shader_derivatives"
+)";
+  const std::string mode = R"(
+OpExecutionMode %main LocalSize 8 8 1
+)";
+  CompileSuccessfully(
+      GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr("OpImageQueryLod requires Fragment execution model"));
+              HasSubstr("OpImageQueryLod requires DerivativeGroupQuadsNV or "
+                        "DerivativeGroupLinearNV execution mode for GLCompute "
+                        "execution model"));
 }
 
 TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
@@ -3743,9 +3794,55 @@ TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
 
   CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr("ImplicitLod instructions require Fragment or "
+                        "GLCompute execution model"));
+}
+
+TEST_F(ValidateImage, ImplicitLodComputeShaderDerivatives) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
+)";
+
+  const std::string extra = R"(
+OpCapability ComputeDerivativeGroupLinearNV
+OpExtension "SPV_NV_compute_shader_derivatives"
+)";
+  const std::string mode = R"(
+OpExecutionMode %main LocalSize 8 8 1
+OpExecutionMode %main DerivativeGroupLinearNV
+)";
+  CompileSuccessfully(
+      GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
+  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, ImplicitLodComputeShaderDerivativesMissingMode) {
+  const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
+)";
+
+  const std::string extra = R"(
+OpCapability ComputeDerivativeGroupLinearNV
+OpExtension "SPV_NV_compute_shader_derivatives"
+)";
+  const std::string mode = R"(
+OpExecutionMode %main LocalSize 8 8 1
+)";
+  CompileSuccessfully(
+      GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
+  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
   EXPECT_THAT(
       getDiagnosticString(),
-      HasSubstr("ImplicitLod instructions require Fragment execution model"));
+      HasSubstr("ImplicitLod instructions require DerivativeGroupQuadsNV or "
+                "DerivativeGroupLinearNV execution mode for GLCompute "
+                "execution model"));
 }
 
 TEST_F(ValidateImage, ReadSubpassDataWrongExecutionModel) {
@@ -3779,7 +3876,7 @@ TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -3907,7 +4004,7 @@ TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4001,7 +4098,7 @@ TEST_F(ValidateImage, SparseFetchSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4218,7 +4315,7 @@ TEST_F(ValidateImage, SparseGatherSuccess) {
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4359,7 +4456,7 @@ OpCapability StorageImageReadWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4376,7 +4473,7 @@ OpCapability StorageImageReadWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4395,7 +4492,7 @@ OpCapability StorageImageReadWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
@@ -4417,7 +4514,7 @@ OpCapability StorageImageReadWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
@@ -4438,7 +4535,7 @@ OpCapability StorageImageWriteWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4457,7 +4554,7 @@ OpCapability StorageImageReadWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
@@ -4478,7 +4575,7 @@ OpCapability StorageImageWriteWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
@@ -4499,7 +4596,7 @@ OpCapability StorageImageWriteWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
@@ -4522,7 +4619,7 @@ OpCapability VulkanMemoryModelKHR
 OpCapability VulkanMemoryModelDeviceScopeKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4539,7 +4636,7 @@ OpCapability StorageImageReadWithoutFormat
 OpCapability VulkanMemoryModelKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
@@ -4562,7 +4659,7 @@ OpCapability VulkanMemoryModelKHR
 OpCapability VulkanMemoryModelDeviceScopeKHR
 OpExtension "SPV_KHR_vulkan_memory_model"
 )";
-  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
+  CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
                                          SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
                           .c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
@@ -4609,7 +4706,7 @@ TEST_F(ValidateImage, SignExtendV13Bad) {
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
 )";
 
-  EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment",
+  EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
                                                 SPV_ENV_UNIVERSAL_1_3)),
               HasSubstr("Invalid image operand 'SignExtend'"));
 }
@@ -4620,7 +4717,7 @@ TEST_F(ValidateImage, ZeroExtendV13Bad) {
 %res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
 )";
 
-  EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment",
+  EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
                                                 SPV_ENV_UNIVERSAL_1_3)),
               HasSubstr("Invalid image operand 'ZeroExtend'"));
 }
@@ -4634,7 +4731,7 @@ TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));
@@ -4649,7 +4746,7 @@ TEST_F(ValidateImage, SignExtendScalarSIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));
@@ -4663,7 +4760,7 @@ TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));
@@ -4677,7 +4774,7 @@ TEST_F(ValidateImage, SignExtendVectorSIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));
@@ -4695,7 +4792,7 @@ TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));
@@ -4710,7 +4807,7 @@ TEST_F(ValidateImage, ZeroExtendScalarSIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));
@@ -4724,7 +4821,7 @@ TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));
@@ -4738,7 +4835,7 @@ TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) {
   const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
 
   CompileSuccessfully(
-      GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
+      GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
       SPV_ENV_UNIVERSAL_1_4);
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
   EXPECT_THAT(getDiagnosticString(), Eq(""));

+ 0 - 1
3rdparty/spirv-tools/utils/check_copyright.py

@@ -16,7 +16,6 @@
 current directory.  Optionally insert them.  When inserting, replaces
 an MIT or Khronos free use license with Apache 2.
 """
-from __future__ import print_function
 
 import argparse
 import fileinput

+ 0 - 2
3rdparty/spirv-tools/utils/check_symbol_exports.py

@@ -14,8 +14,6 @@
 # limitations under the License.
 """Checks names of global exports from a library."""
 
-from __future__ import print_function
-
 import os.path
 import re
 import subprocess

+ 65 - 61
3rdparty/spirv-tools/utils/generate_grammar_tables.py

@@ -14,8 +14,6 @@
 # limitations under the License.
 """Generates various info tables from SPIR-V JSON grammar."""
 
-from __future__ import print_function
-
 import errno
 import json
 import os.path
@@ -36,8 +34,8 @@ SPV_AMD_shader_trinary_minmax
 
 
 def make_path_to_file(f):
-    """Makes all ancestor directories to the given file, if they
-    don't yet exist.
+    """Makes all ancestor directories to the given file, if they don't yet
+    exist.
 
     Arguments:
         f: The file whose ancestor directories are to be created.
@@ -53,8 +51,8 @@ def make_path_to_file(f):
 
 
 def convert_min_required_version(version):
-    """Converts the minimal required SPIR-V version encoded in the
-    grammar to the symbol in SPIRV-Tools"""
+    """Converts the minimal required SPIR-V version encoded in the grammar to
+    the symbol in SPIRV-Tools."""
     if version is None:
         return 'SPV_SPIRV_VERSION_WORD(1, 0)'
     if version == 'None':
@@ -63,8 +61,8 @@ def convert_min_required_version(version):
 
 
 def convert_max_required_version(version):
-    """Converts the maximum required SPIR-V version encoded in the
-    grammar to the symbol in SPIRV-Tools"""
+    """Converts the maximum required SPIR-V version encoded in the grammar to
+    the symbol in SPIRV-Tools."""
     if version is None:
         return '0xffffffffu'
     return 'SPV_SPIRV_VERSION_WORD({})'.format(version.replace('.', ','))
@@ -79,7 +77,7 @@ def compose_capability_list(caps):
     Returns:
       a string containing the braced list of SpvCapability* enums named by caps.
     """
-    return "{" + ", ".join(['SpvCapability{}'.format(c) for c in caps]) + "}"
+    return '{' + ', '.join(['SpvCapability{}'.format(c) for c in caps]) + '}'
 
 
 def get_capability_array_name(caps):
@@ -116,8 +114,8 @@ def compose_extension_list(exts):
     Returns:
       a string containing the braced list of extensions named by exts.
     """
-    return "{" + ", ".join(
-        ['spvtools::Extension::k{}'.format(e) for e in exts]) + "}"
+    return '{' + ', '.join(
+        ['spvtools::Extension::k{}'.format(e) for e in exts]) + '}'
 
 
 def get_extension_array_name(extensions):
@@ -148,8 +146,8 @@ def generate_extension_arrays(extensions):
 
 
 def convert_operand_kind(operand_tuple):
-    """Returns the corresponding operand type used in spirv-tools for
-    the given operand kind and quantifier used in the JSON grammar.
+    """Returns the corresponding operand type used in spirv-tools for the given
+    operand kind and quantifier used in the JSON grammar.
 
     Arguments:
       - operand_tuple: a tuple of two elements:
@@ -211,8 +209,8 @@ def convert_operand_kind(operand_tuple):
 
 
 class InstInitializer(object):
-    """Instances holds a SPIR-V instruction suitable for printing as
-    the initializer for spv_opcode_desc_t."""
+    """Instances holds a SPIR-V instruction suitable for printing as the
+    initializer for spv_opcode_desc_t."""
 
     def __init__(self, opname, caps, exts, operands, version, lastVersion):
         """Initialization.
@@ -244,8 +242,8 @@ class InstInitializer(object):
         self.lastVersion = convert_max_required_version(lastVersion)
 
     def fix_syntax(self):
-        """Fix an instruction's syntax, adjusting for differences between
-        the officially released grammar and how SPIRV-Tools uses the grammar.
+        """Fix an instruction's syntax, adjusting for differences between the
+        officially released grammar and how SPIRV-Tools uses the grammar.
 
         Fixes:
             - ExtInst should not end with SPV_OPERAND_VARIABLE_ID.
@@ -337,8 +335,8 @@ def generate_instruction(inst, is_ext_inst):
 
 
 def generate_instruction_table(inst_table):
-    """Returns the info table containing all SPIR-V instructions,
-    sorted by opcode, and prefixed by capability arrays.
+    """Returns the info table containing all SPIR-V instructions, sorted by
+    opcode, and prefixed by capability arrays.
 
     Note:
       - the built-in sorted() function is guaranteed to be stable.
@@ -435,9 +433,9 @@ def generate_enum_operand_kind_entry(entry, extension_map):
     value = entry.get('value')
     caps = entry.get('capabilities', [])
     if value in extension_map:
-      exts = extension_map[value]
+        exts = extension_map[value]
     else:
-      exts = []
+        exts = []
     params = entry.get('parameters', [])
     params = [p.get('kind') for p in params]
     params = zip(params, [''] * len(params))
@@ -453,8 +451,10 @@ def generate_enum_operand_kind_entry(entry, extension_map):
 
 def generate_enum_operand_kind(enum, synthetic_exts_list):
     """Returns the C definition for the given operand kind.
-    Also appends to |synthetic_exts_list| a list of extension
-    lists used."""
+
+    Also appends to |synthetic_exts_list| a list of extension lists
+    used.
+    """
     kind = enum.get('kind')
     assert kind is not None
 
@@ -462,9 +462,9 @@ def generate_enum_operand_kind(enum, synthetic_exts_list):
     # preserve their order so the first name listed in the grammar
     # as the preferred name for disassembly.
     if enum.get('category') == 'ValueEnum':
-        functor = lambda k: (k['value'])
+        def functor(k): return (k['value'])
     else:
-        functor = lambda k: (int(k['value'], 16))
+        def functor(k): return (int(k['value'], 16))
     entries = sorted(enum.get('enumerants', []), key=functor)
 
     # SubgroupEqMask and SubgroupEqMaskKHR are the same number with
@@ -472,16 +472,16 @@ def generate_enum_operand_kind(enum, synthetic_exts_list):
     # does.  Both should have the extension list.
     # So create a mapping from enum value to the union of the extensions
     # across all those grammar entries.  Preserve order.
-    extension_map = { }
+    extension_map = {}
     for e in entries:
-      value = e.get('value')
-      extension_map[value] = []
+        value = e.get('value')
+        extension_map[value] = []
     for e in entries:
-      value = e.get('value')
-      exts = e.get('extensions', [])
-      for ext in exts:
-        if ext not in extension_map[value]:
-          extension_map[value].append(ext)
+        value = e.get('value')
+        exts = e.get('extensions', [])
+        for ext in exts:
+            if ext not in extension_map[value]:
+                extension_map[value].append(ext)
     synthetic_exts_list.extend(extension_map.values())
 
     name = '{}_{}Entries'.format(PYGEN_VARIABLE_PREFIX, kind)
@@ -544,7 +544,8 @@ def get_extension_list(instructions, operand_kinds):
 
     things_with_an_extensions_field = [item for item in instructions]
 
-    enumerants = sum([item.get('enumerants', []) for item in operand_kinds], [])
+    enumerants = sum([item.get('enumerants', [])
+                      for item in operand_kinds], [])
 
     things_with_an_extensions_field.extend(enumerants)
 
@@ -553,11 +554,12 @@ def get_extension_list(instructions, operand_kinds):
                       if item.get('extensions')], [])
 
     for item in EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split():
-        # If it's already listed in a grammar, then don't put it in the
-        # special exceptions list.
-        assert item not in extensions, "Extension %s is already in a grammar file" % item
+            # If it's already listed in a grammar, then don't put it in the
+            # special exceptions list.
+        assert item not in extensions, 'Extension %s is already in a grammar file' % item
 
-    extensions.extend(EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split())
+    extensions.extend(
+        EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split())
 
     # Validator would ignore type declaration unique check. Should only be used
     # for legacy autogenerated test files containing multiple instances of the
@@ -570,8 +572,7 @@ def get_extension_list(instructions, operand_kinds):
 
 def get_capabilities(operand_kinds):
     """Returns capabilities as a list of JSON objects, in order of
-    appearance.
-    """
+    appearance."""
     enumerants = sum([item.get('enumerants', []) for item in operand_kinds
                       if item.get('kind') in ['Capability']], [])
     return enumerants
@@ -620,6 +621,7 @@ def generate_string_to_extension_mapping(extensions):
 
 def generate_capability_to_string_mapping(operand_kinds):
     """Returns mapping function from capabilities to corresponding strings.
+
     We take care to avoid emitting duplicate values.
     """
     function = 'const char* CapabilityToString(SpvCapability capability) {\n'
@@ -649,8 +651,8 @@ def generate_all_string_enum_mappings(extensions, operand_kinds):
 
 
 def precondition_operand_kinds(operand_kinds):
-    """For operand kinds that have the same number, make sure they all have
-    the same extension list"""
+    """For operand kinds that have the same number, make sure they all have the
+    same extension list."""
     return operand_kinds
 
 
@@ -751,45 +753,47 @@ def main():
         if args.core_insts_output is not None:
             make_path_to_file(args.core_insts_output)
             make_path_to_file(args.operand_kinds_output)
-            print(generate_instruction_table(core_grammar['instructions']),
-              file=open(args.core_insts_output, 'w'))
-            print(generate_operand_kind_table(operand_kinds),
-              file=open(args.operand_kinds_output, 'w'))
+            with open(args.core_insts_output, 'w') as f:
+                f.write(generate_instruction_table(
+                    core_grammar['instructions']))
+            with open(args.operand_kinds_output, 'w') as f:
+                f.write(generate_operand_kind_table(operand_kinds))
         if args.extension_enum_output is not None:
             make_path_to_file(args.extension_enum_output)
-            print(generate_extension_enum(extensions),
-              file=open(args.extension_enum_output, 'w'))
+            with open(args.extension_enum_output, 'w') as f:
+                f.write(generate_extension_enum(extensions))
         if args.enum_string_mapping_output is not None:
             make_path_to_file(args.enum_string_mapping_output)
-            print(generate_all_string_enum_mappings(extensions, operand_kinds),
-              file=open(args.enum_string_mapping_output, 'w'))
+            with open(args.enum_string_mapping_output, 'w') as f:
+                f.write(generate_all_string_enum_mappings(
+                    extensions, operand_kinds))
 
     if args.extinst_glsl_grammar is not None:
         with open(args.extinst_glsl_grammar) as json_file:
             grammar = json.loads(json_file.read())
             make_path_to_file(args.glsl_insts_output)
-            print(generate_extended_instruction_table(
-                    grammar['instructions'], "glsl"),
-                  file=open(args.glsl_insts_output, 'w'))
+            with open(args.glsl_insts_output, 'w') as f:
+                f.write(generate_extended_instruction_table(
+                    grammar['instructions'], 'glsl'))
 
     if args.extinst_opencl_grammar is not None:
         with open(args.extinst_opencl_grammar) as json_file:
             grammar = json.loads(json_file.read())
             make_path_to_file(args.opencl_insts_output)
-            print(generate_extended_instruction_table(
-                    grammar['instructions'], "opencl"),
-                  file=open(args.opencl_insts_output, 'w'))
+            with open(args.opencl_insts_output, 'w') as f:
+                f.write(generate_extended_instruction_table(
+                    grammar['instructions'], 'opencl'))
 
     if args.extinst_vendor_grammar is not None:
         with open(args.extinst_vendor_grammar) as json_file:
             grammar = json.loads(json_file.read())
             make_path_to_file(args.vendor_insts_output)
             name = args.extinst_vendor_grammar
-            start = name.find("extinst.") + len("extinst.")
-            name = name[start:-len(".grammar.json")].replace("-", "_")
-            print(generate_extended_instruction_table(
-                    grammar['instructions'], name),
-                  file=open(args.vendor_insts_output, 'w'))
+            start = name.find('extinst.') + len('extinst.')
+            name = name[start:-len('.grammar.json')].replace('-', '_')
+            with open(args.vendor_insts_output, 'w') as f:
+                f.write(generate_extended_instruction_table(
+                    grammar['instructions'], name))
 
 
 if __name__ == '__main__':

+ 2 - 3
3rdparty/spirv-tools/utils/generate_language_headers.py

@@ -14,8 +14,6 @@
 # limitations under the License.
 """Generates language headers from a JSON grammar file"""
 
-from __future__ import print_function
-
 import errno
 import json
 import os.path
@@ -181,7 +179,8 @@ def main():
                                  version = grammar_json['version'],
                                  revision = grammar_json['revision'])
         make_path_to_file(args.extinst_output_base)
-        print(CGenerator().generate(grammar), file=open(args.extinst_output_base + '.h', 'w'))
+        with open(args.extinst_output_base + '.h', 'w') as f:
+            f.write(CGenerator().generate(grammar))
 
 
 if __name__ == '__main__':

+ 2 - 3
3rdparty/spirv-tools/utils/generate_registry_tables.py

@@ -14,8 +14,6 @@
 # limitations under the License.
 """Generates the vendor tool table from the SPIR-V XML registry."""
 
-from __future__ import print_function
-
 import distutils.dir_util
 import os.path
 import xml.etree.ElementTree
@@ -65,7 +63,8 @@ def main():
        registry = xml.etree.ElementTree.fromstring(xml_in.read())
 
     distutils.dir_util.mkpath(os.path.dirname(args.generator_output))
-    print(generate_vendor_table(registry), file=open(args.generator_output, 'w'))
+    with open(args.generator_output, 'w') as f:
+      f.write(generate_vendor_table(registry))
 
 
 if __name__ == '__main__':

+ 0 - 2
3rdparty/spirv-tools/utils/generate_vim_syntax.py

@@ -14,8 +14,6 @@
 # limitations under the License.
 """Generates Vim syntax rules for SPIR-V assembly (.spvasm) files"""
 
-from __future__ import print_function
-
 import json
 
 PREAMBLE="""" Vim syntax file

+ 0 - 2
3rdparty/spirv-tools/utils/update_build_version.py

@@ -29,8 +29,6 @@
 #    "unknown hash".
 # The string contents are escaped as necessary.
 
-from __future__ import print_function
-
 import datetime
 import errno
 import os

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików