Răsfoiți Sursa

Updated spirv-tools.

Бранимир Караџић 5 ani în urmă
părinte
comite
39d1f8c32c
38 a modificat fișierele cu 631 adăugiri și 419 ștergeri
  1. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  2. 4 0
      3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
  3. 2 0
      3rdparty/spirv-tools/include/generated/extension_enum.inc
  4. 19 1
      3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
  5. 7 6
      3rdparty/spirv-tools/include/spirv-tools/libspirv.h
  6. 8 20
      3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp
  7. 38 32
      3rdparty/spirv-tools/source/CMakeLists.txt
  8. 1 1
      3rdparty/spirv-tools/source/cfa.h
  9. 1 1
      3rdparty/spirv-tools/source/link/CMakeLists.txt
  10. 3 0
      3rdparty/spirv-tools/source/operand.cpp
  11. 3 4
      3rdparty/spirv-tools/source/opt/CMakeLists.txt
  12. 11 14
      3rdparty/spirv-tools/source/opt/ccp_pass.cpp
  13. 3 2
      3rdparty/spirv-tools/source/opt/ccp_pass.h
  14. 59 33
      3rdparty/spirv-tools/source/opt/debug_info_manager.cpp
  15. 13 14
      3rdparty/spirv-tools/source/opt/debug_info_manager.h
  16. 36 0
      3rdparty/spirv-tools/source/opt/empty_pass.h
  17. 3 0
      3rdparty/spirv-tools/source/opt/function.h
  18. 6 0
      3rdparty/spirv-tools/source/opt/inline_pass.cpp
  19. 24 10
      3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.cpp
  20. 1 1
      3rdparty/spirv-tools/source/opt/instruction.cpp
  21. 28 4
      3rdparty/spirv-tools/source/opt/instrument_pass.cpp
  22. 6 2
      3rdparty/spirv-tools/source/opt/instrument_pass.h
  23. 13 1
      3rdparty/spirv-tools/source/opt/ir_loader.cpp
  24. 2 0
      3rdparty/spirv-tools/source/opt/ir_loader.h
  25. 2 2
      3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp
  26. 41 2
      3rdparty/spirv-tools/source/opt/module.cpp
  27. 6 0
      3rdparty/spirv-tools/source/opt/module.h
  28. 2 8
      3rdparty/spirv-tools/source/opt/optimizer.cpp
  29. 1 1
      3rdparty/spirv-tools/source/opt/passes.h
  30. 0 157
      3rdparty/spirv-tools/source/opt/process_lines_pass.cpp
  31. 0 87
      3rdparty/spirv-tools/source/opt/process_lines_pass.h
  32. 73 7
      3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp
  33. 13 0
      3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.h
  34. 2 2
      3rdparty/spirv-tools/source/reduce/CMakeLists.txt
  35. 5 1
      3rdparty/spirv-tools/source/val/validate_atomics.cpp
  36. 176 4
      3rdparty/spirv-tools/source/val/validate_builtins.cpp
  37. 13 0
      3rdparty/spirv-tools/source/val/validate_cfg.cpp
  38. 5 1
      3rdparty/spirv-tools/source/val/validate_image.cpp

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

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

Fișier diff suprimat deoarece este prea mare
+ 4 - 0
3rdparty/spirv-tools/include/generated/enum_string_mapping.inc


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

@@ -15,6 +15,7 @@ kSPV_EXT_fragment_invocation_density,
 kSPV_EXT_fragment_shader_interlock,
 kSPV_EXT_fragment_shader_interlock,
 kSPV_EXT_physical_storage_buffer,
 kSPV_EXT_physical_storage_buffer,
 kSPV_EXT_shader_atomic_float_add,
 kSPV_EXT_shader_atomic_float_add,
+kSPV_EXT_shader_image_int64,
 kSPV_EXT_shader_stencil_export,
 kSPV_EXT_shader_stencil_export,
 kSPV_EXT_shader_viewport_index_layer,
 kSPV_EXT_shader_viewport_index_layer,
 kSPV_GOOGLE_decorate_string,
 kSPV_GOOGLE_decorate_string,
@@ -35,6 +36,7 @@ kSPV_KHR_16bit_storage,
 kSPV_KHR_8bit_storage,
 kSPV_KHR_8bit_storage,
 kSPV_KHR_device_group,
 kSPV_KHR_device_group,
 kSPV_KHR_float_controls,
 kSPV_KHR_float_controls,
+kSPV_KHR_fragment_shading_rate,
 kSPV_KHR_multiview,
 kSPV_KHR_multiview,
 kSPV_KHR_no_integer_wrap_decoration,
 kSPV_KHR_no_integer_wrap_decoration,
 kSPV_KHR_non_semantic_info,
 kSPV_KHR_non_semantic_info,

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

@@ -19,6 +19,7 @@ static const SpvCapability pygen_variable_caps_FragmentFullyCoveredEXT[] = {SpvC
 static const SpvCapability pygen_variable_caps_FragmentShaderPixelInterlockEXT[] = {SpvCapabilityFragmentShaderPixelInterlockEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderPixelInterlockEXT[] = {SpvCapabilityFragmentShaderPixelInterlockEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderSampleInterlockEXT[] = {SpvCapabilityFragmentShaderSampleInterlockEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderSampleInterlockEXT[] = {SpvCapabilityFragmentShaderSampleInterlockEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderShadingRateInterlockEXT[] = {SpvCapabilityFragmentShaderShadingRateInterlockEXT};
 static const SpvCapability pygen_variable_caps_FragmentShaderShadingRateInterlockEXT[] = {SpvCapabilityFragmentShaderShadingRateInterlockEXT};
+static const SpvCapability pygen_variable_caps_FragmentShadingRateKHR[] = {SpvCapabilityFragmentShadingRateKHR};
 static const SpvCapability pygen_variable_caps_FunctionPointersINTEL[] = {SpvCapabilityFunctionPointersINTEL};
 static const SpvCapability pygen_variable_caps_FunctionPointersINTEL[] = {SpvCapabilityFunctionPointersINTEL};
 static const SpvCapability pygen_variable_caps_GenericPointer[] = {SpvCapabilityGenericPointer};
 static const SpvCapability pygen_variable_caps_GenericPointer[] = {SpvCapabilityGenericPointer};
 static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
 static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
@@ -40,6 +41,7 @@ static const SpvCapability pygen_variable_caps_IndirectReferencesINTEL[] = {SpvC
 static const SpvCapability pygen_variable_caps_InputAttachment[] = {SpvCapabilityInputAttachment};
 static const SpvCapability pygen_variable_caps_InputAttachment[] = {SpvCapabilityInputAttachment};
 static const SpvCapability pygen_variable_caps_InputAttachmentShaderNonUniform[] = {SpvCapabilityInputAttachment, SpvCapabilityShaderNonUniform};
 static const SpvCapability pygen_variable_caps_InputAttachmentShaderNonUniform[] = {SpvCapabilityInputAttachment, SpvCapabilityShaderNonUniform};
 static const SpvCapability pygen_variable_caps_Int64[] = {SpvCapabilityInt64};
 static const SpvCapability pygen_variable_caps_Int64[] = {SpvCapabilityInt64};
+static const SpvCapability pygen_variable_caps_Int64ImageEXT[] = {SpvCapabilityInt64ImageEXT};
 static const SpvCapability pygen_variable_caps_Kernel[] = {SpvCapabilityKernel};
 static const SpvCapability pygen_variable_caps_Kernel[] = {SpvCapabilityKernel};
 static const SpvCapability pygen_variable_caps_KernelGroupNonUniform[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform};
 static const SpvCapability pygen_variable_caps_KernelGroupNonUniform[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform};
 static const SpvCapability pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform, SpvCapabilitySubgroupBallotKHR};
 static const SpvCapability pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform, SpvCapabilitySubgroupBallotKHR};
@@ -109,6 +111,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_invocation
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_shader_interlock[] = {spvtools::Extension::kSPV_EXT_fragment_shader_interlock};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_shader_interlock[] = {spvtools::Extension::kSPV_EXT_fragment_shader_interlock};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer[] = {spvtools::Extension::kSPV_EXT_physical_storage_buffer, spvtools::Extension::kSPV_KHR_physical_storage_buffer};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer[] = {spvtools::Extension::kSPV_EXT_physical_storage_buffer, spvtools::Extension::kSPV_KHR_physical_storage_buffer};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_add};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_add};
+static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_image_int64[] = {spvtools::Extension::kSPV_EXT_shader_image_int64};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_stencil_export[] = {spvtools::Extension::kSPV_EXT_shader_stencil_export};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_stencil_export[] = {spvtools::Extension::kSPV_EXT_shader_stencil_export};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_viewport_index_layerSPV_NV_viewport_array2[] = {spvtools::Extension::kSPV_EXT_shader_viewport_index_layer, spvtools::Extension::kSPV_NV_viewport_array2};
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_viewport_index_layerSPV_NV_viewport_array2[] = {spvtools::Extension::kSPV_EXT_shader_viewport_index_layer, spvtools::Extension::kSPV_NV_viewport_array2};
 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_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
@@ -128,6 +131,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_16bit_storage[] = {
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_8bit_storage[] = {spvtools::Extension::kSPV_KHR_8bit_storage};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_8bit_storage[] = {spvtools::Extension::kSPV_KHR_8bit_storage};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_device_group[] = {spvtools::Extension::kSPV_KHR_device_group};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_device_group[] = {spvtools::Extension::kSPV_KHR_device_group};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_float_controls[] = {spvtools::Extension::kSPV_KHR_float_controls};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_float_controls[] = {spvtools::Extension::kSPV_KHR_float_controls};
+static const spvtools::Extension pygen_variable_exts_SPV_KHR_fragment_shading_rate[] = {spvtools::Extension::kSPV_KHR_fragment_shading_rate};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_multiview[] = {spvtools::Extension::kSPV_KHR_multiview};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_multiview[] = {spvtools::Extension::kSPV_KHR_multiview};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_no_integer_wrap_decoration[] = {spvtools::Extension::kSPV_KHR_no_integer_wrap_decoration};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_no_integer_wrap_decoration[] = {spvtools::Extension::kSPV_KHR_no_integer_wrap_decoration};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_post_depth_coverage[] = {spvtools::Extension::kSPV_KHR_post_depth_coverage};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_post_depth_coverage[] = {spvtools::Extension::kSPV_KHR_post_depth_coverage};
@@ -279,6 +283,13 @@ static const spv_operand_desc_t pygen_variable_RayFlagsEntries[] = {
   {"SkipAABBsKHR", 0x0200, 1, pygen_variable_caps_RayTraversalPrimitiveCullingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
   {"SkipAABBsKHR", 0x0200, 1, pygen_variable_caps_RayTraversalPrimitiveCullingProvisionalKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
 };
 };
 
 
+static const spv_operand_desc_t pygen_variable_FragmentShadingRateEntries[] = {
+  {"Vertical2Pixels", 0x0001, 1, pygen_variable_caps_FragmentShadingRateKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"Vertical4Pixels", 0x0002, 1, pygen_variable_caps_FragmentShadingRateKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"Horizontal2Pixels", 0x0004, 1, pygen_variable_caps_FragmentShadingRateKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"Horizontal4Pixels", 0x0008, 1, pygen_variable_caps_FragmentShadingRateKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
+};
+
 static const spv_operand_desc_t pygen_variable_SourceLanguageEntries[] = {
 static const spv_operand_desc_t pygen_variable_SourceLanguageEntries[] = {
   {"Unknown", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Unknown", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"ESSL", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"ESSL", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
@@ -485,7 +496,9 @@ static const spv_operand_desc_t pygen_variable_ImageFormatEntries[] = {
   {"Rg16ui", 36, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Rg16ui", 36, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Rg8ui", 37, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Rg8ui", 37, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"R16ui", 38, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"R16ui", 38, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
-  {"R8ui", 39, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
+  {"R8ui", 39, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
+  {"R64ui", 40, 1, pygen_variable_caps_Int64ImageEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
+  {"R64i", 41, 1, pygen_variable_caps_Int64ImageEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
 };
 };
 
 
 static const spv_operand_desc_t pygen_variable_ImageChannelOrderEntries[] = {
 static const spv_operand_desc_t pygen_variable_ImageChannelOrderEntries[] = {
@@ -700,8 +713,10 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
   {"BaseVertex", 4424, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"BaseVertex", 4424, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"BaseInstance", 4425, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"BaseInstance", 4425, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"DrawIndex", 4426, 2, pygen_variable_caps_DrawParametersMeshShadingNV, 2, pygen_variable_exts_SPV_KHR_shader_draw_parametersSPV_NV_mesh_shader, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"DrawIndex", 4426, 2, pygen_variable_caps_DrawParametersMeshShadingNV, 2, pygen_variable_exts_SPV_KHR_shader_draw_parametersSPV_NV_mesh_shader, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
+  {"PrimitiveShadingRateKHR", 4432, 1, pygen_variable_caps_FragmentShadingRateKHR, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu},
   {"DeviceIndex", 4438, 1, pygen_variable_caps_DeviceGroup, 1, pygen_variable_exts_SPV_KHR_device_group, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"DeviceIndex", 4438, 1, pygen_variable_caps_DeviceGroup, 1, pygen_variable_exts_SPV_KHR_device_group, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"ViewIndex", 4440, 1, pygen_variable_caps_MultiView, 1, pygen_variable_exts_SPV_KHR_multiview, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"ViewIndex", 4440, 1, pygen_variable_caps_MultiView, 1, pygen_variable_exts_SPV_KHR_multiview, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
+  {"ShadingRateKHR", 4444, 1, pygen_variable_caps_FragmentShadingRateKHR, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu},
   {"BaryCoordNoPerspAMD", 4992, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu, 0xffffffffu},
   {"BaryCoordNoPerspAMD", 4992, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu, 0xffffffffu},
   {"BaryCoordNoPerspCentroidAMD", 4993, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu, 0xffffffffu},
   {"BaryCoordNoPerspCentroidAMD", 4993, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu, 0xffffffffu},
   {"BaryCoordNoPerspSampleAMD", 4994, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu, 0xffffffffu},
   {"BaryCoordNoPerspSampleAMD", 4994, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu, 0xffffffffu},
@@ -862,6 +877,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"GroupNonUniformQuad", 68, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"GroupNonUniformQuad", 68, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"ShaderLayer", 69, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"ShaderLayer", 69, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"ShaderViewportIndex", 70, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"ShaderViewportIndex", 70, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
+  {"FragmentShadingRateKHR", 4422, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupBallotKHR", 4423, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupBallotKHR", 4423, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, 0xffffffffu, 0xffffffffu},
   {"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
   {"SubgroupVoteKHR", 4431, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupVoteKHR", 4431, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, {}, 0xffffffffu, 0xffffffffu},
@@ -892,6 +908,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},
   {"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},
   {"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},
   {"ImageReadWriteLodAMD", 5015, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_image_load_store_lod, {}, 0xffffffffu, 0xffffffffu},
+  {"Int64ImageEXT", 5016, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_image_int64, {}, 0xffffffffu, 0xffffffffu},
   {"ShaderClockKHR", 5055, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_clock, {}, 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},
   {"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},
   {"GeometryShaderPassthroughNV", 5251, 1, pygen_variable_caps_Geometry, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu, 0xffffffffu},
@@ -1110,6 +1127,7 @@ static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = {
   {SPV_OPERAND_TYPE_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries},
   {SPV_OPERAND_TYPE_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries},
   {SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, ARRAY_SIZE(pygen_variable_KernelProfilingInfoEntries), pygen_variable_KernelProfilingInfoEntries},
   {SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, ARRAY_SIZE(pygen_variable_KernelProfilingInfoEntries), pygen_variable_KernelProfilingInfoEntries},
   {SPV_OPERAND_TYPE_RAY_FLAGS, ARRAY_SIZE(pygen_variable_RayFlagsEntries), pygen_variable_RayFlagsEntries},
   {SPV_OPERAND_TYPE_RAY_FLAGS, ARRAY_SIZE(pygen_variable_RayFlagsEntries), pygen_variable_RayFlagsEntries},
+  {SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE, ARRAY_SIZE(pygen_variable_FragmentShadingRateEntries), pygen_variable_FragmentShadingRateEntries},
   {SPV_OPERAND_TYPE_SOURCE_LANGUAGE, ARRAY_SIZE(pygen_variable_SourceLanguageEntries), pygen_variable_SourceLanguageEntries},
   {SPV_OPERAND_TYPE_SOURCE_LANGUAGE, ARRAY_SIZE(pygen_variable_SourceLanguageEntries), pygen_variable_SourceLanguageEntries},
   {SPV_OPERAND_TYPE_EXECUTION_MODEL, ARRAY_SIZE(pygen_variable_ExecutionModelEntries), pygen_variable_ExecutionModelEntries},
   {SPV_OPERAND_TYPE_EXECUTION_MODEL, ARRAY_SIZE(pygen_variable_ExecutionModelEntries), pygen_variable_ExecutionModelEntries},
   {SPV_OPERAND_TYPE_ADDRESSING_MODEL, ARRAY_SIZE(pygen_variable_AddressingModelEntries), pygen_variable_AddressingModelEntries},
   {SPV_OPERAND_TYPE_ADDRESSING_MODEL, ARRAY_SIZE(pygen_variable_AddressingModelEntries), pygen_variable_AddressingModelEntries},

+ 7 - 6
3rdparty/spirv-tools/include/spirv-tools/libspirv.h

@@ -176,12 +176,13 @@ typedef enum spv_operand_type_t {
 
 
   // Set 5:  Operands that are a single word bitmask.
   // Set 5:  Operands that are a single word bitmask.
   // Sometimes a set bit indicates the instruction requires still more operands.
   // Sometimes a set bit indicates the instruction requires still more operands.
-  SPV_OPERAND_TYPE_IMAGE,              // SPIR-V Sec 3.14
-  SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,  // SPIR-V Sec 3.15
-  SPV_OPERAND_TYPE_SELECTION_CONTROL,  // SPIR-V Sec 3.22
-  SPV_OPERAND_TYPE_LOOP_CONTROL,       // SPIR-V Sec 3.23
-  SPV_OPERAND_TYPE_FUNCTION_CONTROL,   // SPIR-V Sec 3.24
-  SPV_OPERAND_TYPE_MEMORY_ACCESS,      // SPIR-V Sec 3.26
+  SPV_OPERAND_TYPE_IMAGE,                  // SPIR-V Sec 3.14
+  SPV_OPERAND_TYPE_FP_FAST_MATH_MODE,      // SPIR-V Sec 3.15
+  SPV_OPERAND_TYPE_SELECTION_CONTROL,      // SPIR-V Sec 3.22
+  SPV_OPERAND_TYPE_LOOP_CONTROL,           // SPIR-V Sec 3.23
+  SPV_OPERAND_TYPE_FUNCTION_CONTROL,       // SPIR-V Sec 3.24
+  SPV_OPERAND_TYPE_MEMORY_ACCESS,          // SPIR-V Sec 3.26
+  SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE,  // SPIR-V Sec 3.FSR
 
 
 // The remaining operand types are only used internally by the assembler.
 // The remaining operand types are only used internally by the assembler.
 // There are two categories:
 // There are two categories:

+ 8 - 20
3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp

@@ -536,28 +536,16 @@ Optimizer::PassToken CreateDeadInsertElimPass();
 // eliminated with standard dead code elimination.
 // eliminated with standard dead code elimination.
 Optimizer::PassToken CreateAggressiveDCEPass();
 Optimizer::PassToken CreateAggressiveDCEPass();
 
 
-// Create line propagation pass
-// This pass propagates line information based on the rules for OpLine and
-// OpNoline and clones an appropriate line instruction into every instruction
-// which does not already have debug line instructions.
-//
-// This pass is intended to maximize preservation of source line information
-// through passes which delete, move and clone instructions. Ideally it should
-// be run before any such pass. It is a bookend pass with EliminateDeadLines
-// which can be used to remove redundant line instructions at the end of a
-// run of such passes and reduce final output file size.
+// Creates an empty pass.
+// This is deprecated and will be removed.
+// TODO(jaebaek): remove this pass after handling glslang's broken unit tests.
+//                https://github.com/KhronosGroup/glslang/pull/2440
 Optimizer::PassToken CreatePropagateLineInfoPass();
 Optimizer::PassToken CreatePropagateLineInfoPass();
 
 
-// Create dead line elimination pass
-// This pass eliminates redundant line instructions based on the rules for
-// OpLine and OpNoline. Its main purpose is to reduce the size of the file
-// need to store the SPIR-V without losing line information.
-//
-// This is a bookend pass with PropagateLines which attaches line instructions
-// to every instruction to preserve line information during passes which
-// delete, move and clone instructions. DeadLineElim should be run after
-// PropagateLines and all such subsequent passes. Normally it would be one
-// of the last passes to be run.
+// Creates an empty pass.
+// This is deprecated and will be removed.
+// TODO(jaebaek): remove this pass after handling glslang's broken unit tests.
+//                https://github.com/KhronosGroup/glslang/pull/2440
 Optimizer::PassToken CreateRedundantLineInfoElimPass();
 Optimizer::PassToken CreateRedundantLineInfoElimPass();
 
 
 // Creates a compact ids pass.
 // Creates a compact ids pass.

+ 38 - 32
3rdparty/spirv-tools/source/CMakeLists.txt

@@ -346,58 +346,64 @@ set_source_files_properties(
 
 
 spvtools_pch(SPIRV_SOURCES pch_source)
 spvtools_pch(SPIRV_SOURCES pch_source)
 
 
-add_library(${SPIRV_TOOLS}-static STATIC ${SPIRV_SOURCES})
-spvtools_default_compile_options(${SPIRV_TOOLS}-static)
-target_include_directories(${SPIRV_TOOLS}-static
-  PUBLIC
-    $<BUILD_INTERFACE:${spirv-tools_SOURCE_DIR}/include>
-    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-  PRIVATE ${spirv-tools_BINARY_DIR}
-  PRIVATE ${SPIRV_HEADER_INCLUDE_DIR}
+# spirv_tools_default_target_options() sets the target options that are common
+# for all ${SPIRV_TOOLS} targets.
+function(spirv_tools_default_target_options target)
+  spvtools_default_compile_options(${target})
+  target_include_directories(${target}
+    PUBLIC
+      $<BUILD_INTERFACE:${spirv-tools_SOURCE_DIR}/include>
+      $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+    PRIVATE ${spirv-tools_BINARY_DIR}
+    PRIVATE ${SPIRV_HEADER_INCLUDE_DIR}
   )
   )
-set_property(TARGET ${SPIRV_TOOLS}-static PROPERTY FOLDER "SPIRV-Tools libraries")
-spvtools_check_symbol_exports(${SPIRV_TOOLS}-static)
-add_dependencies(${SPIRV_TOOLS}-static core_tables enum_string_mapping extinst_tables)
-
-# The static target does not have the '-static' suffix.
-set_target_properties(${SPIRV_TOOLS}-static PROPERTIES OUTPUT_NAME "${SPIRV_TOOLS}")
+  set_property(TARGET ${target} PROPERTY FOLDER "SPIRV-Tools libraries")
+  spvtools_check_symbol_exports(${target})
+  add_dependencies(${target} core_tables enum_string_mapping extinst_tables)
+endfunction()
 
 
+# Always build ${SPIRV_TOOLS}-shared. This is expected distro packages, and
+# unlike the other SPIRV_TOOLS target, defaults to hidden symbol visibility.
 add_library(${SPIRV_TOOLS}-shared SHARED ${SPIRV_SOURCES})
 add_library(${SPIRV_TOOLS}-shared SHARED ${SPIRV_SOURCES})
-spvtools_default_compile_options(${SPIRV_TOOLS}-shared)
-target_include_directories(${SPIRV_TOOLS}-shared
-  PUBLIC
-    $<BUILD_INTERFACE:${spirv-tools_SOURCE_DIR}/include>
-    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-  PRIVATE ${spirv-tools_BINARY_DIR}
-  PRIVATE ${SPIRV_HEADER_INCLUDE_DIR}
-  )
+spirv_tools_default_target_options(${SPIRV_TOOLS}-shared)
 set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES CXX_VISIBILITY_PRESET hidden)
 set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES CXX_VISIBILITY_PRESET hidden)
-set_property(TARGET ${SPIRV_TOOLS}-shared PROPERTY FOLDER "SPIRV-Tools libraries")
-spvtools_check_symbol_exports(${SPIRV_TOOLS}-shared)
 target_compile_definitions(${SPIRV_TOOLS}-shared
 target_compile_definitions(${SPIRV_TOOLS}-shared
   PRIVATE SPIRV_TOOLS_IMPLEMENTATION
   PRIVATE SPIRV_TOOLS_IMPLEMENTATION
   PUBLIC SPIRV_TOOLS_SHAREDLIB
   PUBLIC SPIRV_TOOLS_SHAREDLIB
 )
 )
-add_dependencies(${SPIRV_TOOLS}-shared core_tables enum_string_mapping extinst_tables)
 
 
-# Create the "${SPIRV_TOOLS}" target as an alias to either "${SPIRV_TOOLS}-static"
-# or "${SPIRV_TOOLS}-shared" depending on the value of BUILD_SHARED_LIBS.
-if(BUILD_SHARED_LIBS)
+if(SPIRV_TOOLS_BUILD_STATIC)
+  add_library(${SPIRV_TOOLS}-static STATIC ${SPIRV_SOURCES})
+  spirv_tools_default_target_options(${SPIRV_TOOLS}-static)
+  # The static target does not have the '-static' suffix.
+  set_target_properties(${SPIRV_TOOLS}-static PROPERTIES OUTPUT_NAME "${SPIRV_TOOLS}")
+
+  # Create the "${SPIRV_TOOLS}" target as an alias to either "${SPIRV_TOOLS}-static"
+  # or "${SPIRV_TOOLS}-shared" depending on the value of BUILD_SHARED_LIBS.
+  if(BUILD_SHARED_LIBS)
     add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS}-shared)
     add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS}-shared)
-else()
+  else()
     add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS}-static)
     add_library(${SPIRV_TOOLS} ALIAS ${SPIRV_TOOLS}-static)
+  endif()
+
+  set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS}-static ${SPIRV_TOOLS}-shared)
+else()
+  add_library(${SPIRV_TOOLS} ${SPIRV_TOOLS_LIBRARY_TYPE} ${SPIRV_SOURCES})
+  spirv_tools_default_target_options(${SPIRV_TOOLS})
+  set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS} ${SPIRV_TOOLS}-shared)
 endif()
 endif()
 
 
 if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
 if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
   find_library(LIBRT rt)
   find_library(LIBRT rt)
   if(LIBRT)
   if(LIBRT)
-    target_link_libraries(${SPIRV_TOOLS}-static ${LIBRT})
-    target_link_libraries(${SPIRV_TOOLS}-shared ${LIBRT})
+    foreach(target ${SPIRV_TOOLS_TARGETS})
+      target_link_libraries(${target} ${LIBRT})
+    endforeach()
   endif()
   endif()
 endif()
 endif()
 
 
 if(ENABLE_SPIRV_TOOLS_INSTALL)
 if(ENABLE_SPIRV_TOOLS_INSTALL)
-  install(TARGETS ${SPIRV_TOOLS}-static ${SPIRV_TOOLS}-shared EXPORT ${SPIRV_TOOLS}Targets
+  install(TARGETS ${SPIRV_TOOLS_TARGETS} EXPORT ${SPIRV_TOOLS}Targets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
     LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
     LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
     ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
     ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

+ 1 - 1
3rdparty/spirv-tools/source/cfa.h

@@ -127,7 +127,7 @@ class CFA {
 template <class BB>
 template <class BB>
 bool CFA<BB>::FindInWorkList(const std::vector<block_info>& work_list,
 bool CFA<BB>::FindInWorkList(const std::vector<block_info>& work_list,
                              uint32_t id) {
                              uint32_t id) {
-  for (auto& b : work_list) {
+  for (const auto& b : work_list) {
     if (b.block->id() == id) return true;
     if (b.block->id() == id) return true;
   }
   }
   return false;
   return false;

+ 1 - 1
3rdparty/spirv-tools/source/link/CMakeLists.txt

@@ -11,7 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # limitations under the License.
-add_library(SPIRV-Tools-link STATIC
+add_library(SPIRV-Tools-link ${SPIRV_TOOLS_LIBRARY_TYPE}
   linker.cpp
   linker.cpp
 )
 )
 
 

+ 3 - 0
3rdparty/spirv-tools/source/operand.cpp

@@ -208,6 +208,8 @@ const char* spvOperandTypeStr(spv_operand_type_t type) {
     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
     case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
     case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
       return "memory access";
       return "memory access";
+    case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE:
+      return "shading rate";
     case SPV_OPERAND_TYPE_SCOPE_ID:
     case SPV_OPERAND_TYPE_SCOPE_ID:
       return "scope ID";
       return "scope ID";
     case SPV_OPERAND_TYPE_GROUP_OPERATION:
     case SPV_OPERAND_TYPE_GROUP_OPERATION:
@@ -360,6 +362,7 @@ bool spvOperandIsConcreteMask(spv_operand_type_t type) {
     case SPV_OPERAND_TYPE_LOOP_CONTROL:
     case SPV_OPERAND_TYPE_LOOP_CONTROL:
     case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
     case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
+    case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE:
     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
       return true;
       return true;

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

@@ -43,6 +43,7 @@ set(SPIRV_TOOLS_OPT_SOURCES
   eliminate_dead_functions_pass.h
   eliminate_dead_functions_pass.h
   eliminate_dead_functions_util.h
   eliminate_dead_functions_util.h
   eliminate_dead_members_pass.h
   eliminate_dead_members_pass.h
+  empty_pass.h
   feature_manager.h
   feature_manager.h
   fix_storage_class.h
   fix_storage_class.h
   flatten_decoration_pass.h
   flatten_decoration_pass.h
@@ -89,7 +90,6 @@ set(SPIRV_TOOLS_OPT_SOURCES
   pass.h
   pass.h
   pass_manager.h
   pass_manager.h
   private_to_local_pass.h
   private_to_local_pass.h
-  process_lines_pass.h
   propagator.h
   propagator.h
   reduce_load_size.h
   reduce_load_size.h
   redundancy_elimination.h
   redundancy_elimination.h
@@ -196,7 +196,6 @@ set(SPIRV_TOOLS_OPT_SOURCES
   pass.cpp
   pass.cpp
   pass_manager.cpp
   pass_manager.cpp
   private_to_local_pass.cpp
   private_to_local_pass.cpp
-  process_lines_pass.cpp
   propagator.cpp
   propagator.cpp
   reduce_load_size.cpp
   reduce_load_size.cpp
   redundancy_elimination.cpp
   redundancy_elimination.cpp
@@ -233,7 +232,7 @@ endif()
 
 
 spvtools_pch(SPIRV_TOOLS_OPT_SOURCES pch_source_opt)
 spvtools_pch(SPIRV_TOOLS_OPT_SOURCES pch_source_opt)
 
 
-add_library(SPIRV-Tools-opt STATIC ${SPIRV_TOOLS_OPT_SOURCES})
+add_library(SPIRV-Tools-opt ${SPIRV_TOOLS_LIBRARY_TYPE} ${SPIRV_TOOLS_OPT_SOURCES})
 
 
 spvtools_default_compile_options(SPIRV-Tools-opt)
 spvtools_default_compile_options(SPIRV-Tools-opt)
 target_include_directories(SPIRV-Tools-opt
 target_include_directories(SPIRV-Tools-opt
@@ -245,7 +244,7 @@ target_include_directories(SPIRV-Tools-opt
 )
 )
 # We need the assembling and disassembling functionalities in the main library.
 # We need the assembling and disassembling functionalities in the main library.
 target_link_libraries(SPIRV-Tools-opt
 target_link_libraries(SPIRV-Tools-opt
-  PUBLIC ${SPIRV_TOOLS}-static)
+  PUBLIC ${SPIRV_TOOLS_FULL_VISIBILITY})
 
 
 set_property(TARGET SPIRV-Tools-opt PROPERTY FOLDER "SPIRV-Tools libraries")
 set_property(TARGET SPIRV-Tools-opt PROPERTY FOLDER "SPIRV-Tools libraries")
 spvtools_check_symbol_exports(SPIRV-Tools-opt)
 spvtools_check_symbol_exports(SPIRV-Tools-opt)

+ 11 - 14
3rdparty/spirv-tools/source/opt/ccp_pass.cpp

@@ -135,23 +135,15 @@ SSAPropagator::PropStatus CCPPass::VisitAssignment(Instruction* instr) {
     }
     }
     return it->second;
     return it->second;
   };
   };
-  uint32_t next_id = context()->module()->IdBound();
   Instruction* folded_inst =
   Instruction* folded_inst =
       context()->get_instruction_folder().FoldInstructionToConstant(instr,
       context()->get_instruction_folder().FoldInstructionToConstant(instr,
                                                                     map_func);
                                                                     map_func);
+
   if (folded_inst != nullptr) {
   if (folded_inst != nullptr) {
     // We do not want to change the body of the function by adding new
     // We do not want to change the body of the function by adding new
     // instructions.  When folding we can only generate new constants.
     // instructions.  When folding we can only generate new constants.
     assert(folded_inst->IsConstant() && "CCP is only interested in constant.");
     assert(folded_inst->IsConstant() && "CCP is only interested in constant.");
     values_[instr->result_id()] = folded_inst->result_id();
     values_[instr->result_id()] = folded_inst->result_id();
-
-    // If the folded instruction has just been created, its result ID will
-    // match the previous ID bound. When this happens, we need to indicate
-    // that CCP has modified the IR, independently of whether the constant is
-    // actually propagated. See
-    // https://github.com/KhronosGroup/SPIRV-Tools/issues/3636 for details.
-    if (folded_inst->result_id() >= next_id) created_new_constant_ = true;
-
     return SSAPropagator::kInteresting;
     return SSAPropagator::kInteresting;
   }
   }
 
 
@@ -278,10 +270,14 @@ bool CCPPass::ReplaceValues() {
   // Even if we make no changes to the function's IR, propagation may have
   // Even if we make no changes to the function's IR, propagation may have
   // created new constants.  Even if those constants cannot be replaced in
   // created new constants.  Even if those constants cannot be replaced in
   // the IR, the constant definition itself is a change.  To reflect this,
   // the IR, the constant definition itself is a change.  To reflect this,
-  // we initialize the IR changed indicator with the value of the
-  // created_new_constant_ indicator.  For an example, see the bug reported
-  // in https://github.com/KhronosGroup/SPIRV-Tools/issues/3636.
-  bool changed_ir = created_new_constant_;
+  // we check whether the next ID to be given by the module is different than
+  // the original bound ID. If that happens, new instructions were added to the
+  // module during propagation.
+  //
+  // See https://github.com/KhronosGroup/SPIRV-Tools/issues/3636 and
+  // https://github.com/KhronosGroup/SPIRV-Tools/issues/3991 for details.
+  bool changed_ir = (context()->module()->IdBound() > original_id_bound_);
+
   for (const auto& it : values_) {
   for (const auto& it : values_) {
     uint32_t id = it.first;
     uint32_t id = it.first;
     uint32_t cst_id = it.second;
     uint32_t cst_id = it.second;
@@ -290,6 +286,7 @@ bool CCPPass::ReplaceValues() {
       changed_ir |= context()->ReplaceAllUsesWith(id, cst_id);
       changed_ir |= context()->ReplaceAllUsesWith(id, cst_id);
     }
     }
   }
   }
+
   return changed_ir;
   return changed_ir;
 }
 }
 
 
@@ -329,7 +326,7 @@ void CCPPass::Initialize() {
     }
     }
   }
   }
 
 
-  created_new_constant_ = false;
+  original_id_bound_ = context()->module()->IdBound();
 }
 }
 
 
 Pass::Status CCPPass::Process() {
 Pass::Status CCPPass::Process() {

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

@@ -106,8 +106,9 @@ class CCPPass : public MemPass {
   // Propagator engine used.
   // Propagator engine used.
   std::unique_ptr<SSAPropagator> propagator_;
   std::unique_ptr<SSAPropagator> propagator_;
 
 
-  // True if the pass created new constant instructions during propagation.
-  bool created_new_constant_;
+  // Value for the module's ID bound before running CCP. Used to detect whether
+  // propagation created new instructions.
+  uint32_t original_id_bound_;
 };
 };
 
 
 }  // namespace opt
 }  // namespace opt

+ 59 - 33
3rdparty/spirv-tools/source/opt/debug_info_manager.cpp

@@ -40,7 +40,6 @@ static const uint32_t kDebugLocalVariableOperandParentIndex = 9;
 static const uint32_t kExtInstInstructionInIdx = 1;
 static const uint32_t kExtInstInstructionInIdx = 1;
 static const uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
 static const uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
 static const uint32_t kDebugLocalVariableOperandFlagsIndex = 10;
 static const uint32_t kDebugLocalVariableOperandFlagsIndex = 10;
-static const uint32_t kDebugLocalVariableOperandArgNumberIndex = 11;
 
 
 namespace spvtools {
 namespace spvtools {
 namespace opt {
 namespace opt {
@@ -441,32 +440,40 @@ bool DebugInfoManager::IsAncestorOfScope(uint32_t scope, uint32_t ancestor) {
   return false;
   return false;
 }
 }
 
 
-Instruction* DebugInfoManager::GetDebugLocalVariableFromDeclare(
-    Instruction* dbg_declare) {
-  assert(dbg_declare);
+bool DebugInfoManager::IsDeclareVisibleToInstr(Instruction* dbg_declare,
+                                               Instruction* scope) {
+  assert(dbg_declare != nullptr);
+  assert(scope != nullptr);
+
+  std::vector<uint32_t> scope_ids;
+  if (scope->opcode() == SpvOpPhi) {
+    scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
+    for (uint32_t i = 0; i < scope->NumInOperands(); i += 2) {
+      auto* value = context()->get_def_use_mgr()->GetDef(
+          scope->GetSingleWordInOperand(i));
+      if (value != nullptr)
+        scope_ids.push_back(value->GetDebugScope().GetLexicalScope());
+    }
+  } else {
+    scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
+  }
+
   uint32_t dbg_local_var_id =
   uint32_t dbg_local_var_id =
       dbg_declare->GetSingleWordOperand(kDebugDeclareOperandLocalVariableIndex);
       dbg_declare->GetSingleWordOperand(kDebugDeclareOperandLocalVariableIndex);
   auto dbg_local_var_itr = id_to_dbg_inst_.find(dbg_local_var_id);
   auto dbg_local_var_itr = id_to_dbg_inst_.find(dbg_local_var_id);
   assert(dbg_local_var_itr != id_to_dbg_inst_.end());
   assert(dbg_local_var_itr != id_to_dbg_inst_.end());
-  return dbg_local_var_itr->second;
-}
-
-bool DebugInfoManager::IsFunctionParameter(Instruction* dbg_local_var) const {
-  // If a DebugLocalVariable has ArgNumber operand, it is a function parameter.
-  return dbg_local_var->NumOperands() >
-         kDebugLocalVariableOperandArgNumberIndex;
-}
-
-bool DebugInfoManager::IsLocalVariableVisibleToInstr(Instruction* dbg_local_var,
-                                                     uint32_t instr_scope_id) {
-  if (instr_scope_id == kNoDebugScope) return false;
-
-  uint32_t decl_scope_id = dbg_local_var->GetSingleWordOperand(
+  uint32_t decl_scope_id = dbg_local_var_itr->second->GetSingleWordOperand(
       kDebugLocalVariableOperandParentIndex);
       kDebugLocalVariableOperandParentIndex);
 
 
   // If the scope of DebugDeclare is an ancestor scope of the instruction's
   // If the scope of DebugDeclare is an ancestor scope of the instruction's
   // scope, the local variable is visible to the instruction.
   // scope, the local variable is visible to the instruction.
-  return IsAncestorOfScope(instr_scope_id, decl_scope_id);
+  for (uint32_t scope_id : scope_ids) {
+    if (scope_id != kNoDebugScope &&
+        IsAncestorOfScope(scope_id, decl_scope_id)) {
+      return true;
+    }
+  }
+  return false;
 }
 }
 
 
 Instruction* DebugInfoManager::AddDebugValueWithIndex(
 Instruction* DebugInfoManager::AddDebugValueWithIndex(
@@ -509,26 +516,21 @@ Instruction* DebugInfoManager::AddDebugValueWithIndex(
 
 
 void DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
 void DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
     Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
     Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
-    Instruction* insert_pos) {
+    Instruction* insert_pos,
+    std::unordered_set<Instruction*>* invisible_decls) {
   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
   auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
   if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return;
   if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return;
 
 
-  uint32_t instr_scope_id = scope_and_line->GetDebugScope().GetLexicalScope();
   for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
   for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
-    // If it declares a function parameter, the store instruction for the
-    // function parameter can exist out of the function parameter's scope
-    // because of the function inlining. We always add DebugValue for a
-    // function parameter next to the DebugDeclare regardless of the scope.
-    auto* dbg_local_var = GetDebugLocalVariableFromDeclare(dbg_decl_or_val);
-    bool is_function_param = IsFunctionParameter(dbg_local_var);
-    if (!is_function_param &&
-        !IsLocalVariableVisibleToInstr(dbg_local_var, instr_scope_id))
+    if (scope_and_line &&
+        !IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) {
+      if (invisible_decls) invisible_decls->insert(dbg_decl_or_val);
       continue;
       continue;
+    }
 
 
     // Avoid inserting the new DebugValue between OpPhi or OpVariable
     // Avoid inserting the new DebugValue between OpPhi or OpVariable
     // instructions.
     // instructions.
-    Instruction* insert_before = is_function_param ? dbg_decl_or_val->NextNode()
-                                                   : insert_pos->NextNode();
+    Instruction* insert_before = insert_pos->NextNode();
     while (insert_before->opcode() == SpvOpPhi ||
     while (insert_before->opcode() == SpvOpPhi ||
            insert_before->opcode() == SpvOpVariable) {
            insert_before->opcode() == SpvOpVariable) {
       insert_before = insert_before->NextNode();
       insert_before = insert_before->NextNode();
@@ -545,12 +547,36 @@ void DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
                                    kDebugValueOperandLocalVariableIndex),
                                    kDebugValueOperandLocalVariableIndex),
                                value_id, 0, index_id, insert_before);
                                value_id, 0, index_id, insert_before);
     assert(added_dbg_value != nullptr);
     assert(added_dbg_value != nullptr);
-    added_dbg_value->UpdateDebugInfoFrom(is_function_param ? dbg_decl_or_val
-                                                           : scope_and_line);
+    added_dbg_value->UpdateDebugInfoFrom(scope_and_line ? scope_and_line
+                                                        : dbg_decl_or_val);
     AnalyzeDebugInst(added_dbg_value);
     AnalyzeDebugInst(added_dbg_value);
   }
   }
 }
 }
 
 
+bool DebugInfoManager::AddDebugValueForDecl(Instruction* dbg_decl,
+                                            uint32_t value_id) {
+  if (dbg_decl == nullptr || !IsDebugDeclare(dbg_decl)) return false;
+
+  std::unique_ptr<Instruction> dbg_val(dbg_decl->Clone(context()));
+  dbg_val->SetResultId(context()->TakeNextId());
+  dbg_val->SetInOperand(kExtInstInstructionInIdx,
+                        {OpenCLDebugInfo100DebugValue});
+  dbg_val->SetOperand(kDebugDeclareOperandVariableIndex, {value_id});
+  dbg_val->SetOperand(kDebugValueOperandExpressionIndex,
+                      {GetEmptyDebugExpression()->result_id()});
+
+  auto* added_dbg_val = dbg_decl->InsertBefore(std::move(dbg_val));
+  AnalyzeDebugInst(added_dbg_val);
+  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
+    context()->get_def_use_mgr()->AnalyzeInstDefUse(added_dbg_val);
+  if (context()->AreAnalysesValid(
+          IRContext::Analysis::kAnalysisInstrToBlockMapping)) {
+    auto insert_blk = context()->get_instr_block(dbg_decl);
+    context()->set_instr_block(added_dbg_val, insert_blk);
+  }
+  return true;
+}
+
 uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare(
 uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare(
     Instruction* inst) {
     Instruction* inst) {
   if (inst->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugValue) return 0;
   if (inst->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugValue) return 0;

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

@@ -144,9 +144,11 @@ class DebugInfoManager {
   // Generates a DebugValue instruction with value |value_id| for every local
   // Generates a DebugValue instruction with value |value_id| for every local
   // variable that is in the scope of |scope_and_line| and whose memory is
   // variable that is in the scope of |scope_and_line| and whose memory is
   // |variable_id| and inserts it after the instruction |insert_pos|.
   // |variable_id| and inserts it after the instruction |insert_pos|.
-  void AddDebugValueIfVarDeclIsVisible(Instruction* scope_and_line,
-                                       uint32_t variable_id, uint32_t value_id,
-                                       Instruction* insert_pos);
+  // |invisible_decls| returns DebugDeclares invisible to |scope_and_line|.
+  void AddDebugValueIfVarDeclIsVisible(
+      Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
+      Instruction* insert_pos,
+      std::unordered_set<Instruction*>* invisible_decls);
 
 
   // Generates a DebugValue instruction with |dbg_local_var_id|, |value_id|,
   // Generates a DebugValue instruction with |dbg_local_var_id|, |value_id|,
   // |expr_id|, |index_id| operands and inserts it before |insert_before|.
   // |expr_id|, |index_id| operands and inserts it before |insert_before|.
@@ -155,6 +157,11 @@ class DebugInfoManager {
                                       uint32_t index_id,
                                       uint32_t index_id,
                                       Instruction* insert_before);
                                       Instruction* insert_before);
 
 
+  // Adds DebugValue for DebugDeclare |dbg_decl|. The new DebugValue has the
+  // same line, scope, and operands but it uses |value_id| for value. Returns
+  // weather it succeeds or not.
+  bool AddDebugValueForDecl(Instruction* dbg_decl, uint32_t value_id);
+
   // Erases |instr| from data structures of this class.
   // Erases |instr| from data structures of this class.
   void ClearDebugInfo(Instruction* instr);
   void ClearDebugInfo(Instruction* instr);
 
 
@@ -215,17 +222,9 @@ class DebugInfoManager {
   // of |scope|.
   // of |scope|.
   bool IsAncestorOfScope(uint32_t scope, uint32_t ancestor);
   bool IsAncestorOfScope(uint32_t scope, uint32_t ancestor);
 
 
-  // Returns the DebugLocalVariable declared by |dbg_declare|.
-  Instruction* GetDebugLocalVariableFromDeclare(Instruction* dbg_declare);
-
-  // Returns true if the DebugLocalVariable |dbg_local_var| is a function
-  // parameter.
-  bool IsFunctionParameter(Instruction* dbg_local_var) const;
-
-  // Returns true if the DebugLocalVariable |dbg_local_var| is visible
-  // in the scope of an instruction |instr_scope_id|.
-  bool IsLocalVariableVisibleToInstr(Instruction* dbg_local_var,
-                                     uint32_t instr_scope_id);
+  // Returns true if the declaration of a local variable |dbg_declare|
+  // is visible in the scope of an instruction |instr_scope_id|.
+  bool IsDeclareVisibleToInstr(Instruction* dbg_declare, Instruction* scope);
 
 
   // Returns the parent scope of the scope |child_scope|.
   // Returns the parent scope of the scope |child_scope|.
   uint32_t GetParentScope(uint32_t child_scope);
   uint32_t GetParentScope(uint32_t child_scope);

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

@@ -0,0 +1,36 @@
+// Copyright (c) 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOURCE_OPT_EMPTY_PASS_H_
+#define SOURCE_OPT_EMPTY_PASS_H_
+
+#include "source/opt/pass.h"
+
+namespace spvtools {
+namespace opt {
+
+// Documented in optimizer.hpp
+class EmptyPass : public Pass {
+ public:
+  EmptyPass() {}
+
+  const char* name() const override { return "empty-pass"; }
+
+  Status Process() override { return Status::SuccessWithoutChange; }
+};
+
+}  // namespace opt
+}  // namespace spvtools
+
+#endif  // SOURCE_OPT_EMPTY_PASS_H_

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

@@ -94,6 +94,9 @@ class Function {
   // Returns function's return type id
   // Returns function's return type id
   inline uint32_t type_id() const { return def_inst_->type_id(); }
   inline uint32_t type_id() const { return def_inst_->type_id(); }
 
 
+  // Returns the function's control mask
+  inline uint32_t control_mask() const { return def_inst_->GetSingleWordInOperand(0); }
+
   // Returns the entry basic block for this function.
   // Returns the entry basic block for this function.
   const std::unique_ptr<BasicBlock>& entry() const { return blocks_.front(); }
   const std::unique_ptr<BasicBlock>& entry() const { return blocks_.front(); }
 
 

+ 6 - 0
3rdparty/spirv-tools/source/opt/inline_pass.cpp

@@ -727,6 +727,12 @@ void InlinePass::AnalyzeReturns(Function* func) {
 bool InlinePass::IsInlinableFunction(Function* func) {
 bool InlinePass::IsInlinableFunction(Function* func) {
   // We can only inline a function if it has blocks.
   // We can only inline a function if it has blocks.
   if (func->cbegin() == func->cend()) return false;
   if (func->cbegin() == func->cend()) return false;
+
+  // Do not inline functions with DontInline flag.
+  if (func->control_mask() & SpvFunctionControlDontInlineMask) {
+    return false;
+  }
+
   // Do not inline functions with returns in loops. Currently early return
   // Do not inline functions with returns in loops. Currently early return
   // functions are inlined by wrapping them in a one trip loop and implementing
   // functions are inlined by wrapping them in a one trip loop and implementing
   // the returns as a branch to the loop's merge block. However, this can only
   // the returns as a branch to the loop's merge block. However, this can only

+ 24 - 10
3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.cpp

@@ -349,8 +349,9 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(ref_analysis* ref,
                                    : SpvDecorationArrayStride;
                                    : SpvDecorationArrayStride;
         uint32_t arr_stride = FindStride(curr_ty_id, stride_deco);
         uint32_t arr_stride = FindStride(curr_ty_id, stride_deco);
         uint32_t arr_stride_id = builder->GetUintConstantId(arr_stride);
         uint32_t arr_stride_id = builder->GetUintConstantId(arr_stride);
+        uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         Instruction* curr_offset_inst = builder->AddBinaryOp(
         Instruction* curr_offset_inst = builder->AddBinaryOp(
-            GetUintId(), SpvOpIMul, arr_stride_id, curr_idx_id);
+            GetUintId(), SpvOpIMul, arr_stride_id, curr_idx_32b_id);
         curr_offset_id = curr_offset_inst->result_id();
         curr_offset_id = curr_offset_inst->result_id();
         // Get element type for next step
         // Get element type for next step
         curr_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
         curr_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
@@ -360,8 +361,9 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(ref_analysis* ref,
         uint32_t comp_ty_id = curr_ty_inst->GetSingleWordInOperand(0u);
         uint32_t comp_ty_id = curr_ty_inst->GetSingleWordInOperand(0u);
         uint32_t vec_stride = ByteSize(comp_ty_id);
         uint32_t vec_stride = ByteSize(comp_ty_id);
         uint32_t vec_stride_id = builder->GetUintConstantId(vec_stride);
         uint32_t vec_stride_id = builder->GetUintConstantId(vec_stride);
+        uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         Instruction* curr_offset_inst = builder->AddBinaryOp(
         Instruction* curr_offset_inst = builder->AddBinaryOp(
-            GetUintId(), SpvOpIMul, vec_stride_id, curr_idx_id);
+            GetUintId(), SpvOpIMul, vec_stride_id, curr_idx_32b_id);
         curr_offset_id = curr_offset_inst->result_id();
         curr_offset_id = curr_offset_inst->result_id();
         // Get element type for next step
         // Get element type for next step
         curr_ty_id = comp_ty_id;
         curr_ty_id = comp_ty_id;
@@ -434,18 +436,27 @@ void InstBindlessCheckPass::GenCheckCode(
   new_blk_ptr.reset(new BasicBlock(std::move(invalid_label)));
   new_blk_ptr.reset(new BasicBlock(std::move(invalid_label)));
   builder.SetInsertPoint(&*new_blk_ptr);
   builder.SetInsertPoint(&*new_blk_ptr);
   uint32_t u_index_id = GenUintCastCode(ref->desc_idx_id, &builder);
   uint32_t u_index_id = GenUintCastCode(ref->desc_idx_id, &builder);
-  if (offset_id != 0)
+  if (offset_id != 0) {
+    // Buffer OOB
+    uint32_t u_offset_id = GenUintCastCode(offset_id, &builder);
+    uint32_t u_length_id = GenUintCastCode(length_id, &builder);
     GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
     GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
-                        {error_id, u_index_id, offset_id, length_id}, &builder);
-  else if (buffer_bounds_enabled_)
-    // So all error modes will use same debug stream write function
+                        {error_id, u_index_id, u_offset_id, u_length_id},
+                        &builder);
+  } else if (buffer_bounds_enabled_) {
+    // Uninitialized Descriptor - Return additional unused zero so all error
+    // modes will use same debug stream write function
+    uint32_t u_length_id = GenUintCastCode(length_id, &builder);
     GenDebugStreamWrite(
     GenDebugStreamWrite(
         uid2offset_[ref->ref_inst->unique_id()], stage_idx,
         uid2offset_[ref->ref_inst->unique_id()], stage_idx,
-        {error_id, u_index_id, length_id, builder.GetUintConstantId(0)},
+        {error_id, u_index_id, u_length_id, builder.GetUintConstantId(0)},
         &builder);
         &builder);
-  else
+  } else {
+    // Uninitialized Descriptor - Normal error return
+    uint32_t u_length_id = GenUintCastCode(length_id, &builder);
     GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
     GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
-                        {error_id, u_index_id, length_id}, &builder);
+                        {error_id, u_index_id, u_length_id}, &builder);
+  }
   // Remember last invalid block id
   // Remember last invalid block id
   uint32_t last_invalid_blk_id = new_blk_ptr->GetLabelInst()->result_id();
   uint32_t last_invalid_blk_id = new_blk_ptr->GetLabelInst()->result_id();
   // Gen zero for invalid  reference
   // Gen zero for invalid  reference
@@ -516,8 +527,11 @@ void InstBindlessCheckPass::GenDescIdxCheckCode(
   // Generate full runtime bounds test code with true branch
   // Generate full runtime bounds test code with true branch
   // being full reference and false branch being debug output and zero
   // being full reference and false branch being debug output and zero
   // for the referenced value.
   // for the referenced value.
+  uint32_t desc_idx_32b_id = Gen32BitCvtCode(ref.desc_idx_id, &builder);
+  uint32_t length_32b_id = Gen32BitCvtCode(length_id, &builder);
   Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), SpvOpULessThan,
   Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), SpvOpULessThan,
-                                              ref.desc_idx_id, length_id);
+                                              desc_idx_32b_id, length_32b_id);
+  ref.desc_idx_id = desc_idx_32b_id;
   GenCheckCode(ult_inst->result_id(), error_id, 0u, length_id, stage_idx, &ref,
   GenCheckCode(ult_inst->result_id(), error_id, 0u, length_id, stage_idx, &ref,
                new_blocks);
                new_blocks);
   // Move original block's remaining code into remainder/merge block and add
   // Move original block's remaining code into remainder/merge block and add

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

@@ -527,7 +527,7 @@ void Instruction::UpdateDebugInfoFrom(const Instruction* from) {
   if (from == nullptr) return;
   if (from == nullptr) return;
   clear_dbg_line_insts();
   clear_dbg_line_insts();
   if (!from->dbg_line_insts().empty())
   if (!from->dbg_line_insts().empty())
-    dbg_line_insts().push_back(from->dbg_line_insts()[0]);
+    dbg_line_insts().push_back(from->dbg_line_insts().back());
   SetDebugScope(from->GetDebugScope());
   SetDebugScope(from->GetDebugScope());
   if (!IsDebugLineInst(opcode()) &&
   if (!IsDebugLineInst(opcode()) &&
       context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {
       context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {

+ 28 - 4
3rdparty/spirv-tools/source/opt/instrument_pass.cpp

@@ -88,12 +88,36 @@ std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) {
   return newLabel;
   return newLabel;
 }
 }
 
 
+uint32_t InstrumentPass::Gen32BitCvtCode(uint32_t val_id,
+                                         InstructionBuilder* builder) {
+  // Convert integer value to 32-bit if necessary
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  uint32_t val_ty_id = get_def_use_mgr()->GetDef(val_id)->type_id();
+  analysis::Integer* val_ty = type_mgr->GetType(val_ty_id)->AsInteger();
+  if (val_ty->width() == 32) return val_id;
+  bool is_signed = val_ty->IsSigned();
+  analysis::Integer val_32b_ty(32, is_signed);
+  analysis::Type* val_32b_reg_ty = type_mgr->GetRegisteredType(&val_32b_ty);
+  uint32_t val_32b_reg_ty_id = type_mgr->GetId(val_32b_reg_ty);
+  if (is_signed)
+    return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpSConvert, val_id)
+        ->result_id();
+  else
+    return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpUConvert, val_id)
+        ->result_id();
+}
+
 uint32_t InstrumentPass::GenUintCastCode(uint32_t val_id,
 uint32_t InstrumentPass::GenUintCastCode(uint32_t val_id,
                                          InstructionBuilder* builder) {
                                          InstructionBuilder* builder) {
-  // Cast value to 32-bit unsigned if necessary
-  if (get_def_use_mgr()->GetDef(val_id)->type_id() == GetUintId())
-    return val_id;
-  return builder->AddUnaryOp(GetUintId(), SpvOpBitcast, val_id)->result_id();
+  // Convert value to 32-bit if necessary
+  uint32_t val_32b_id = Gen32BitCvtCode(val_id, builder);
+  // Cast value to unsigned if necessary
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  uint32_t val_ty_id = get_def_use_mgr()->GetDef(val_32b_id)->type_id();
+  analysis::Integer* val_ty = type_mgr->GetType(val_ty_id)->AsInteger();
+  if (!val_ty->IsSigned()) return val_32b_id;
+  return builder->AddUnaryOp(GetUintId(), SpvOpBitcast, val_32b_id)
+      ->result_id();
 }
 }
 
 
 void InstrumentPass::GenDebugOutputFieldCode(uint32_t base_offset_id,
 void InstrumentPass::GenDebugOutputFieldCode(uint32_t base_offset_id,

+ 6 - 2
3rdparty/spirv-tools/source/opt/instrument_pass.h

@@ -213,8 +213,12 @@ class InstrumentPass : public Pass {
   uint32_t GenDebugDirectRead(const std::vector<uint32_t>& offset_ids,
   uint32_t GenDebugDirectRead(const std::vector<uint32_t>& offset_ids,
                               InstructionBuilder* builder);
                               InstructionBuilder* builder);
 
 
-  // Generate code to cast |value_id| to unsigned, if needed. Return
-  // an id to the unsigned equivalent.
+  // Generate code to convert integer |value_id| to 32bit, if needed. Return
+  // an id to the 32bit equivalent.
+  uint32_t Gen32BitCvtCode(uint32_t value_id, InstructionBuilder* builder);
+
+  // Generate code to cast integer |value_id| to 32bit unsigned, if needed.
+  // Return an id to the Uint equivalent.
   uint32_t GenUintCastCode(uint32_t value_id, InstructionBuilder* builder);
   uint32_t GenUintCastCode(uint32_t value_id, InstructionBuilder* builder);
 
 
   // Return new label.
   // Return new label.

+ 13 - 1
3rdparty/spirv-tools/source/opt/ir_loader.cpp

@@ -41,6 +41,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
   ++inst_index_;
   ++inst_index_;
   const auto opcode = static_cast<SpvOp>(inst->opcode);
   const auto opcode = static_cast<SpvOp>(inst->opcode);
   if (IsDebugLineInst(opcode)) {
   if (IsDebugLineInst(opcode)) {
+    last_line_inst_.reset();
     dbg_line_info_.push_back(
     dbg_line_info_.push_back(
         Instruction(module()->context(), *inst, last_dbg_scope_));
         Instruction(module()->context(), *inst, last_dbg_scope_));
     return true;
     return true;
@@ -90,7 +91,16 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
 
 
   std::unique_ptr<Instruction> spv_inst(
   std::unique_ptr<Instruction> spv_inst(
       new Instruction(module()->context(), *inst, std::move(dbg_line_info_)));
       new Instruction(module()->context(), *inst, std::move(dbg_line_info_)));
-  dbg_line_info_.clear();
+  if (!spv_inst->dbg_line_insts().empty()) {
+    if (spv_inst->dbg_line_insts().back().opcode() != SpvOpNoLine) {
+      last_line_inst_ = std::unique_ptr<Instruction>(
+          spv_inst->dbg_line_insts().back().Clone(module()->context()));
+    }
+    dbg_line_info_.clear();
+  } else if (last_line_inst_ != nullptr) {
+    last_line_inst_->SetDebugScope(last_dbg_scope_);
+    spv_inst->dbg_line_insts().push_back(*last_line_inst_);
+  }
 
 
   const char* src = source_.c_str();
   const char* src = source_.c_str();
   spv_position_t loc = {inst_index_, 0, 0};
   spv_position_t loc = {inst_index_, 0, 0};
@@ -141,6 +151,8 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
     function_->AddBasicBlock(std::move(block_));
     function_->AddBasicBlock(std::move(block_));
     block_ = nullptr;
     block_ = nullptr;
     last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
     last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
+    last_line_inst_.reset();
+    dbg_line_info_.clear();
   } else {
   } else {
     if (function_ == nullptr) {  // Outside function definition
     if (function_ == nullptr) {  // Outside function definition
       SPIRV_ASSERT(consumer_, block_ == nullptr);
       SPIRV_ASSERT(consumer_, block_ == nullptr);

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

@@ -78,6 +78,8 @@ class IrLoader {
   std::unique_ptr<BasicBlock> block_;
   std::unique_ptr<BasicBlock> block_;
   // Line related debug instructions accumulated thus far.
   // Line related debug instructions accumulated thus far.
   std::vector<Instruction> dbg_line_info_;
   std::vector<Instruction> dbg_line_info_;
+  // Line instruction that should be applied to the next instruction.
+  std::unique_ptr<Instruction> last_line_inst_;
 
 
   // The last DebugScope information that IrLoader::AddInstruction() handled.
   // The last DebugScope information that IrLoader::AddInstruction() handled.
   DebugScope last_dbg_scope_;
   DebugScope last_dbg_scope_;

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

@@ -149,8 +149,8 @@ bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) {
     const analysis::Type* store_type = var_type->AsPointer()->pointee_type();
     const analysis::Type* store_type = var_type->AsPointer()->pointee_type();
     if (!(store_type->AsStruct() || store_type->AsArray())) {
     if (!(store_type->AsStruct() || store_type->AsArray())) {
       context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
       context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
-          store_inst, var_id, store_inst->GetSingleWordInOperand(1),
-          store_inst);
+          nullptr, var_id, store_inst->GetSingleWordInOperand(1), store_inst,
+          nullptr);
       context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
       context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
     }
     }
   }
   }

+ 41 - 2
3rdparty/spirv-tools/source/opt/module.cpp

@@ -143,8 +143,38 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
 
 
   size_t bound_idx = binary->size() - 2;
   size_t bound_idx = binary->size() - 2;
   DebugScope last_scope(kNoDebugScope, kNoInlinedAt);
   DebugScope last_scope(kNoDebugScope, kNoInlinedAt);
-  auto write_inst = [binary, skip_nop, &last_scope,
-                     this](const Instruction* i) {
+  const Instruction* last_line_inst = nullptr;
+  bool between_merge_and_branch = false;
+  auto write_inst = [binary, skip_nop, &last_scope, &last_line_inst,
+                     &between_merge_and_branch, this](const Instruction* i) {
+    // Skip emitting line instructions between merge and branch instructions.
+    auto opcode = i->opcode();
+    if (between_merge_and_branch &&
+        (opcode == SpvOpLine || opcode == SpvOpNoLine)) {
+      return;
+    }
+    between_merge_and_branch = false;
+    if (last_line_inst != nullptr) {
+      // If the current instruction is OpLine and it is the same with
+      // the last line instruction that is still effective (can be applied
+      // to the next instruction), we skip writing the current instruction.
+      if (opcode == SpvOpLine) {
+        uint32_t operand_index = 0;
+        if (last_line_inst->WhileEachInOperand(
+                [&operand_index, i](const uint32_t* word) {
+                  assert(i->NumInOperandWords() > operand_index);
+                  return *word == i->GetSingleWordInOperand(operand_index++);
+                })) {
+          return;
+        }
+      } else if (opcode != SpvOpNoLine && i->dbg_line_insts().empty()) {
+        // If the current instruction does not have the line information,
+        // the last line information is not effective any more. Emit OpNoLine
+        // to specify it.
+        binary->push_back((1 << 16) | static_cast<uint16_t>(SpvOpNoLine));
+        last_line_inst = nullptr;
+      }
+    }
     if (!(skip_nop && i->IsNop())) {
     if (!(skip_nop && i->IsNop())) {
       const auto& scope = i->GetDebugScope();
       const auto& scope = i->GetDebugScope();
       if (scope != last_scope) {
       if (scope != last_scope) {
@@ -157,6 +187,15 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
 
 
       i->ToBinaryWithoutAttachedDebugInsts(binary);
       i->ToBinaryWithoutAttachedDebugInsts(binary);
     }
     }
+    // Update the last line instruction.
+    if (IsTerminatorInst(opcode) || opcode == SpvOpNoLine) {
+      last_line_inst = nullptr;
+    } else if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
+      between_merge_and_branch = true;
+      last_line_inst = nullptr;
+    } else if (opcode == SpvOpLine) {
+      last_line_inst = i;
+    }
   };
   };
   ForEachInst(write_inst, true);
   ForEachInst(write_inst, true);
 
 

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

@@ -246,6 +246,12 @@ class Module {
   // If |skip_nop| is true and this is a OpNop, do nothing.
   // If |skip_nop| is true and this is a OpNop, do nothing.
   void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
   void ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const;
 
 
+  // Pushes the binary segments for this instruction into the back of *|binary|
+  // including all OpLine and OpNoLine even if we can skip emitting some line
+  // instructions. If |skip_nop| is true and this is a OpNop, do nothing.
+  void ToBinaryWithAllOpLines(std::vector<uint32_t>* binary,
+                              bool skip_nop) const;
+
   // Returns 1 more than the maximum Id value mentioned in the module.
   // Returns 1 more than the maximum Id value mentioned in the module.
   uint32_t ComputeIdBound() const;
   uint32_t ComputeIdBound() const;
 
 

+ 2 - 8
3rdparty/spirv-tools/source/opt/optimizer.cpp

@@ -339,10 +339,6 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
     RegisterPass(CreateDescriptorScalarReplacementPass());
     RegisterPass(CreateDescriptorScalarReplacementPass());
   } else if (pass_name == "eliminate-dead-code-aggressive") {
   } else if (pass_name == "eliminate-dead-code-aggressive") {
     RegisterPass(CreateAggressiveDCEPass());
     RegisterPass(CreateAggressiveDCEPass());
-  } else if (pass_name == "propagate-line-info") {
-    RegisterPass(CreatePropagateLineInfoPass());
-  } else if (pass_name == "eliminate-redundant-line-info") {
-    RegisterPass(CreateRedundantLineInfoElimPass());
   } else if (pass_name == "eliminate-insert-extract") {
   } else if (pass_name == "eliminate-insert-extract") {
     RegisterPass(CreateInsertExtractElimPass());
     RegisterPass(CreateInsertExtractElimPass());
   } else if (pass_name == "eliminate-local-single-block") {
   } else if (pass_name == "eliminate-local-single-block") {
@@ -758,13 +754,11 @@ Optimizer::PassToken CreateAggressiveDCEPass() {
 }
 }
 
 
 Optimizer::PassToken CreatePropagateLineInfoPass() {
 Optimizer::PassToken CreatePropagateLineInfoPass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::ProcessLinesPass>(opt::kLinesPropagateLines));
+  return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
 }
 }
 
 
 Optimizer::PassToken CreateRedundantLineInfoElimPass() {
 Optimizer::PassToken CreateRedundantLineInfoElimPass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::ProcessLinesPass>(opt::kLinesEliminateDeadLines));
+  return MakeUnique<Optimizer::PassToken::Impl>(MakeUnique<opt::EmptyPass>());
 }
 }
 
 
 Optimizer::PassToken CreateCompactIdsPass() {
 Optimizer::PassToken CreateCompactIdsPass() {

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

@@ -35,6 +35,7 @@
 #include "source/opt/eliminate_dead_constant_pass.h"
 #include "source/opt/eliminate_dead_constant_pass.h"
 #include "source/opt/eliminate_dead_functions_pass.h"
 #include "source/opt/eliminate_dead_functions_pass.h"
 #include "source/opt/eliminate_dead_members_pass.h"
 #include "source/opt/eliminate_dead_members_pass.h"
+#include "source/opt/empty_pass.h"
 #include "source/opt/fix_storage_class.h"
 #include "source/opt/fix_storage_class.h"
 #include "source/opt/flatten_decoration_pass.h"
 #include "source/opt/flatten_decoration_pass.h"
 #include "source/opt/fold_spec_constant_op_and_composite_pass.h"
 #include "source/opt/fold_spec_constant_op_and_composite_pass.h"
@@ -61,7 +62,6 @@
 #include "source/opt/merge_return_pass.h"
 #include "source/opt/merge_return_pass.h"
 #include "source/opt/null_pass.h"
 #include "source/opt/null_pass.h"
 #include "source/opt/private_to_local_pass.h"
 #include "source/opt/private_to_local_pass.h"
-#include "source/opt/process_lines_pass.h"
 #include "source/opt/reduce_load_size.h"
 #include "source/opt/reduce_load_size.h"
 #include "source/opt/redundancy_elimination.h"
 #include "source/opt/redundancy_elimination.h"
 #include "source/opt/relax_float_ops_pass.h"
 #include "source/opt/relax_float_ops_pass.h"

+ 0 - 157
3rdparty/spirv-tools/source/opt/process_lines_pass.cpp

@@ -1,157 +0,0 @@
-// Copyright (c) 2018 The Khronos Group Inc.
-// Copyright (c) 2018 Valve Corporation
-// Copyright (c) 2018 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "source/opt/process_lines_pass.h"
-
-#include <set>
-#include <unordered_set>
-#include <vector>
-
-namespace {
-
-// Input Operand Indices
-static const int kSpvLineFileInIdx = 0;
-static const int kSpvLineLineInIdx = 1;
-static const int kSpvLineColInIdx = 2;
-
-}  // anonymous namespace
-
-namespace spvtools {
-namespace opt {
-
-Pass::Status ProcessLinesPass::Process() {
-  bool modified = ProcessLines();
-  return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
-}
-
-bool ProcessLinesPass::ProcessLines() {
-  bool modified = false;
-  uint32_t file_id = 0;
-  uint32_t line = 0;
-  uint32_t col = 0;
-  // Process types, globals, constants
-  for (Instruction& inst : get_module()->types_values())
-    modified |= line_process_func_(&inst, &file_id, &line, &col);
-  // Process functions
-  for (Function& function : *get_module()) {
-    modified |= line_process_func_(&function.DefInst(), &file_id, &line, &col);
-    function.ForEachParam(
-        [this, &modified, &file_id, &line, &col](Instruction* param) {
-          modified |= line_process_func_(param, &file_id, &line, &col);
-        });
-    for (BasicBlock& block : function) {
-      modified |=
-          line_process_func_(block.GetLabelInst(), &file_id, &line, &col);
-      for (Instruction& inst : block) {
-        modified |= line_process_func_(&inst, &file_id, &line, &col);
-        // Don't process terminal instruction if preceeded by merge
-        if (inst.opcode() == SpvOpSelectionMerge ||
-            inst.opcode() == SpvOpLoopMerge)
-          break;
-      }
-      // Nullify line info after each block.
-      file_id = 0;
-    }
-    modified |= line_process_func_(function.EndInst(), &file_id, &line, &col);
-  }
-  return modified;
-}
-
-bool ProcessLinesPass::PropagateLine(Instruction* inst, uint32_t* file_id,
-                                     uint32_t* line, uint32_t* col) {
-  bool modified = false;
-  // only the last debug instruction needs to be considered
-  auto line_itr = inst->dbg_line_insts().rbegin();
-  // if no line instructions, propagate previous info
-  if (line_itr == inst->dbg_line_insts().rend()) {
-    // if no current line info, add OpNoLine, else OpLine
-    if (*file_id == 0)
-      inst->dbg_line_insts().push_back(Instruction(context(), SpvOpNoLine));
-    else
-      inst->dbg_line_insts().push_back(Instruction(
-          context(), SpvOpLine, 0, 0,
-          {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {*file_id}},
-           {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {*line}},
-           {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {*col}}}));
-    modified = true;
-  } else {
-    // else pre-existing line instruction, so update source line info
-    if (line_itr->opcode() == SpvOpNoLine) {
-      *file_id = 0;
-    } else {
-      assert(line_itr->opcode() == SpvOpLine && "unexpected debug inst");
-      *file_id = line_itr->GetSingleWordInOperand(kSpvLineFileInIdx);
-      *line = line_itr->GetSingleWordInOperand(kSpvLineLineInIdx);
-      *col = line_itr->GetSingleWordInOperand(kSpvLineColInIdx);
-    }
-  }
-  return modified;
-}
-
-bool ProcessLinesPass::EliminateDeadLines(Instruction* inst, uint32_t* file_id,
-                                          uint32_t* line, uint32_t* col) {
-  // If no debug line instructions, return without modifying lines
-  if (inst->dbg_line_insts().empty()) return false;
-  // Only the last debug instruction needs to be considered; delete all others
-  bool modified = inst->dbg_line_insts().size() > 1;
-  Instruction last_inst = inst->dbg_line_insts().back();
-  inst->dbg_line_insts().clear();
-  // If last line is OpNoLine
-  if (last_inst.opcode() == SpvOpNoLine) {
-    // If no propagated line info, throw away redundant OpNoLine
-    if (*file_id == 0) {
-      modified = true;
-      // Else replace OpNoLine and propagate no line info
-    } else {
-      inst->dbg_line_insts().push_back(last_inst);
-      *file_id = 0;
-    }
-  } else {
-    // Else last line is OpLine
-    assert(last_inst.opcode() == SpvOpLine && "unexpected debug inst");
-    // If propagated info matches last line, throw away last line
-    if (*file_id == last_inst.GetSingleWordInOperand(kSpvLineFileInIdx) &&
-        *line == last_inst.GetSingleWordInOperand(kSpvLineLineInIdx) &&
-        *col == last_inst.GetSingleWordInOperand(kSpvLineColInIdx)) {
-      modified = true;
-    } else {
-      // Else replace last line and propagate line info
-      *file_id = last_inst.GetSingleWordInOperand(kSpvLineFileInIdx);
-      *line = last_inst.GetSingleWordInOperand(kSpvLineLineInIdx);
-      *col = last_inst.GetSingleWordInOperand(kSpvLineColInIdx);
-      inst->dbg_line_insts().push_back(last_inst);
-    }
-  }
-  return modified;
-}
-
-ProcessLinesPass::ProcessLinesPass(uint32_t func_id) {
-  if (func_id == kLinesPropagateLines) {
-    line_process_func_ = [this](Instruction* inst, uint32_t* file_id,
-                                uint32_t* line, uint32_t* col) {
-      return PropagateLine(inst, file_id, line, col);
-    };
-  } else {
-    assert(func_id == kLinesEliminateDeadLines && "unknown Lines param");
-    line_process_func_ = [this](Instruction* inst, uint32_t* file_id,
-                                uint32_t* line, uint32_t* col) {
-      return EliminateDeadLines(inst, file_id, line, col);
-    };
-  }
-}
-
-}  // namespace opt
-}  // namespace spvtools

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

@@ -1,87 +0,0 @@
-// Copyright (c) 2018 The Khronos Group Inc.
-// Copyright (c) 2018 Valve Corporation
-// Copyright (c) 2018 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SOURCE_OPT_PROPAGATE_LINES_PASS_H_
-#define SOURCE_OPT_PROPAGATE_LINES_PASS_H_
-
-#include "source/opt/function.h"
-#include "source/opt/ir_context.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-namespace {
-
-// Constructor Parameters
-static const int kLinesPropagateLines = 0;
-static const int kLinesEliminateDeadLines = 1;
-
-}  // anonymous namespace
-
-// See optimizer.hpp for documentation.
-class ProcessLinesPass : public Pass {
-  using LineProcessFunction =
-      std::function<bool(Instruction*, uint32_t*, uint32_t*, uint32_t*)>;
-
- public:
-  ProcessLinesPass(uint32_t func_id);
-  ~ProcessLinesPass() override = default;
-
-  const char* name() const override { return "propagate-lines"; }
-
-  // See optimizer.hpp for this pass' user documentation.
-  Status Process() override;
-
-  IRContext::Analysis GetPreservedAnalyses() override {
-    return IRContext::kAnalysisDefUse |
-           IRContext::kAnalysisInstrToBlockMapping |
-           IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
-           IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
-           IRContext::kAnalysisNameMap | IRContext::kAnalysisConstants |
-           IRContext::kAnalysisTypes;
-  }
-
- private:
-  // If |inst| has no debug line instruction, create one with
-  // |file_id, line, col|. If |inst| has debug line instructions, set
-  // |file_id, line, col| from the last. |file_id| equals 0 indicates no line
-  // info is available. Return true if |inst| modified.
-  bool PropagateLine(Instruction* inst, uint32_t* file_id, uint32_t* line,
-                     uint32_t* col);
-
-  // If last debug line instruction of |inst| matches |file_id, line, col|,
-  // delete all debug line instructions of |inst|. If they do not match,
-  // replace all debug line instructions of |inst| with new line instruction
-  // set from |file_id, line, col|. If |inst| has no debug line instructions,
-  // do not modify |inst|. |file_id| equals 0 indicates no line info is
-  // available. Return true if |inst| modified.
-  bool EliminateDeadLines(Instruction* inst, uint32_t* file_id, uint32_t* line,
-                          uint32_t* col);
-
-  // Apply lpfn() to all type, constant, global variable and function
-  // instructions in their physical order.
-  bool ProcessLines();
-
-  // A function that calls either PropagateLine or EliminateDeadLines.
-  // Initialized by the class constructor.
-  LineProcessFunction line_process_func_;
-};
-
-}  // namespace opt
-}  // namespace spvtools
-
-#endif  // SOURCE_OPT_PROPAGATE_LINES_PASS_H_

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

@@ -66,6 +66,7 @@ namespace opt {
 namespace {
 namespace {
 const uint32_t kStoreValIdInIdx = 1;
 const uint32_t kStoreValIdInIdx = 1;
 const uint32_t kVariableInitIdInIdx = 1;
 const uint32_t kVariableInitIdInIdx = 1;
+const uint32_t kDebugDeclareOperandVariableIdx = 5;
 }  // namespace
 }  // namespace
 
 
 std::string SSARewriter::PhiCandidate::PrettyPrint(const CFG* cfg) const {
 std::string SSARewriter::PhiCandidate::PrettyPrint(const CFG* cfg) const {
@@ -241,8 +242,8 @@ uint32_t SSARewriter::AddPhiOperands(PhiCandidate* phi_candidate) {
   return repl_id;
   return repl_id;
 }
 }
 
 
-uint32_t SSARewriter::GetReachingDef(uint32_t var_id, BasicBlock* bb) {
-  // If |var_id| has a definition in |bb|, return it.
+uint32_t SSARewriter::GetValueAtBlock(uint32_t var_id, BasicBlock* bb) {
+  assert(bb != nullptr);
   const auto& bb_it = defs_at_block_.find(bb);
   const auto& bb_it = defs_at_block_.find(bb);
   if (bb_it != defs_at_block_.end()) {
   if (bb_it != defs_at_block_.end()) {
     const auto& current_defs = bb_it->second;
     const auto& current_defs = bb_it->second;
@@ -251,9 +252,15 @@ uint32_t SSARewriter::GetReachingDef(uint32_t var_id, BasicBlock* bb) {
       return var_it->second;
       return var_it->second;
     }
     }
   }
   }
+  return 0;
+}
+
+uint32_t SSARewriter::GetReachingDef(uint32_t var_id, BasicBlock* bb) {
+  // If |var_id| has a definition in |bb|, return it.
+  uint32_t val_id = GetValueAtBlock(var_id, bb);
+  if (val_id != 0) return val_id;
 
 
   // Otherwise, look up the value for |var_id| in |bb|'s predecessors.
   // Otherwise, look up the value for |var_id| in |bb|'s predecessors.
-  uint32_t val_id = 0;
   auto& predecessors = pass_->cfg()->preds(bb->id());
   auto& predecessors = pass_->cfg()->preds(bb->id());
   if (predecessors.size() == 1) {
   if (predecessors.size() == 1) {
     // If |bb| has exactly one predecessor, we look for |var_id|'s definition
     // If |bb| has exactly one predecessor, we look for |var_id|'s definition
@@ -308,7 +315,7 @@ void SSARewriter::ProcessStore(Instruction* inst, BasicBlock* bb) {
   if (pass_->IsTargetVar(var_id)) {
   if (pass_->IsTargetVar(var_id)) {
     WriteVariable(var_id, bb, val_id);
     WriteVariable(var_id, bb, val_id);
     pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
     pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
-        inst, var_id, val_id, inst);
+        inst, var_id, val_id, inst, &decls_invisible_to_value_assignment_);
 
 
 #if SSA_REWRITE_DEBUGGING_LEVEL > 1
 #if SSA_REWRITE_DEBUGGING_LEVEL > 1
     std::cerr << "\tFound store '%" << var_id << " = %" << val_id << "': "
     std::cerr << "\tFound store '%" << var_id << " = %" << val_id << "': "
@@ -439,8 +446,6 @@ bool SSARewriter::ApplyReplacements() {
 
 
   // Add Phi instructions from completed Phi candidates.
   // Add Phi instructions from completed Phi candidates.
   std::vector<Instruction*> generated_phis;
   std::vector<Instruction*> generated_phis;
-  // Add DebugValue instructions for Phi instructions.
-  std::vector<Instruction*> dbg_values_for_phis;
   for (const PhiCandidate* phi_candidate : phis_to_generate_) {
   for (const PhiCandidate* phi_candidate : phis_to_generate_) {
 #if SSA_REWRITE_DEBUGGING_LEVEL > 2
 #if SSA_REWRITE_DEBUGGING_LEVEL > 2
     std::cerr << "Phi candidate: " << phi_candidate->PrettyPrint(pass_->cfg())
     std::cerr << "Phi candidate: " << phi_candidate->PrettyPrint(pass_->cfg())
@@ -493,7 +498,7 @@ bool SSARewriter::ApplyReplacements() {
     insert_it->SetDebugScope(local_var->GetDebugScope());
     insert_it->SetDebugScope(local_var->GetDebugScope());
     pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
     pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible(
         &*insert_it, phi_candidate->var_id(), phi_candidate->result_id(),
         &*insert_it, phi_candidate->var_id(), phi_candidate->result_id(),
-        &*insert_it);
+        &*insert_it, &decls_invisible_to_value_assignment_);
 
 
     modified = true;
     modified = true;
   }
   }
@@ -581,6 +586,61 @@ void SSARewriter::FinalizePhiCandidates() {
   }
   }
 }
 }
 
 
+Pass::Status SSARewriter::AddDebugValuesForInvisibleDebugDecls(Function* fp) {
+  // For the cases the value assignment is invisible to DebugDeclare e.g.,
+  // the argument passing for an inlined function.
+  //
+  // Before inlining foo(int x):
+  //   a = 3;
+  //   foo(3);
+  // After inlining:
+  //   a = 3; // we want to specify "DebugValue: %x = %int_3"
+  //   foo and x disappeared!
+  //
+  // We want to specify the value for the variable using |defs_at_block_[bb]|,
+  // where |bb| is the basic block contains the decl.
+  DominatorAnalysis* dom_tree = pass_->context()->GetDominatorAnalysis(fp);
+  Pass::Status status = Pass::Status::SuccessWithoutChange;
+  for (auto* decl : decls_invisible_to_value_assignment_) {
+    uint32_t var_id =
+        decl->GetSingleWordOperand(kDebugDeclareOperandVariableIdx);
+    auto* var = pass_->get_def_use_mgr()->GetDef(var_id);
+    if (var->opcode() == SpvOpFunctionParameter) continue;
+
+    auto* bb = pass_->context()->get_instr_block(decl);
+    uint32_t value_id = GetValueAtBlock(var_id, bb);
+    Instruction* value = nullptr;
+    if (value_id) value = pass_->get_def_use_mgr()->GetDef(value_id);
+
+    // If |value| is defined before the function body, it dominates |decl|.
+    // If |value| dominates |decl|, we can set it as DebugValue.
+    if (value && (pass_->context()->get_instr_block(value) == nullptr ||
+                  dom_tree->Dominates(value, decl))) {
+      if (!pass_->context()->get_debug_info_mgr()->AddDebugValueForDecl(
+              decl, value->result_id())) {
+        return Pass::Status::Failure;
+      }
+    } else {
+      // If |value| in the same basic block does not dominate |decl|, we can
+      // assign the value in the immediate dominator.
+      value_id = GetValueAtBlock(var_id, dom_tree->ImmediateDominator(bb));
+      if (value_id &&
+          !pass_->context()->get_debug_info_mgr()->AddDebugValueForDecl(
+              decl, value_id)) {
+        return Pass::Status::Failure;
+      }
+    }
+
+    // DebugDeclares of target variables will be removed by
+    // SSARewritePass::Process().
+    if (!pass_->IsTargetVar(var_id)) {
+      pass_->context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
+    }
+    status = Pass::Status::SuccessWithChange;
+  }
+  return status;
+}
+
 Pass::Status SSARewriter::RewriteFunctionIntoSSA(Function* fp) {
 Pass::Status SSARewriter::RewriteFunctionIntoSSA(Function* fp) {
 #if SSA_REWRITE_DEBUGGING_LEVEL > 0
 #if SSA_REWRITE_DEBUGGING_LEVEL > 0
   std::cerr << "Function before SSA rewrite:\n"
   std::cerr << "Function before SSA rewrite:\n"
@@ -610,6 +670,12 @@ Pass::Status SSARewriter::RewriteFunctionIntoSSA(Function* fp) {
   // Finally, apply all the replacements in the IR.
   // Finally, apply all the replacements in the IR.
   bool modified = ApplyReplacements();
   bool modified = ApplyReplacements();
 
 
+  auto status = AddDebugValuesForInvisibleDebugDecls(fp);
+  if (status == Pass::Status::SuccessWithChange ||
+      status == Pass::Status::Failure) {
+    return status;
+  }
+
 #if SSA_REWRITE_DEBUGGING_LEVEL > 0
 #if SSA_REWRITE_DEBUGGING_LEVEL > 0
   std::cerr << "\n\n\nFunction after SSA rewrite:\n"
   std::cerr << "\n\n\nFunction after SSA rewrite:\n"
             << fp->PrettyPrint(0) << "\n";
             << fp->PrettyPrint(0) << "\n";

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

@@ -192,6 +192,10 @@ class SSARewriter {
     }
     }
   }
   }
 
 
+  // Returns the value of |var_id| at |bb| if |defs_at_block_| contains it.
+  // Otherwise, returns 0.
+  uint32_t GetValueAtBlock(uint32_t var_id, BasicBlock* bb);
+
   // Processes the store operation |inst| in basic block |bb|. This extracts
   // Processes the store operation |inst| in basic block |bb|. This extracts
   // the variable ID being stored into, determines whether the variable is an
   // the variable ID being stored into, determines whether the variable is an
   // SSA-target variable, and, if it is, it stores its value in the
   // SSA-target variable, and, if it is, it stores its value in the
@@ -249,6 +253,11 @@ class SSARewriter {
   // candidates.
   // candidates.
   void FinalizePhiCandidates();
   void FinalizePhiCandidates();
 
 
+  // Adds DebugValues for DebugDeclares in
+  // |decls_invisible_to_value_assignment_|. Returns whether the function was
+  // modified or not, and whether or not the conversion was successful.
+  Pass::Status AddDebugValuesForInvisibleDebugDecls(Function* fp);
+
   // Prints the table of Phi candidates to std::cerr.
   // Prints the table of Phi candidates to std::cerr.
   void PrintPhiCandidates() const;
   void PrintPhiCandidates() const;
 
 
@@ -286,6 +295,10 @@ class SSARewriter {
 
 
   // Memory pass requesting the SSA rewriter.
   // Memory pass requesting the SSA rewriter.
   MemPass* pass_;
   MemPass* pass_;
+
+  // Set of DebugDeclare instructions that are not added as DebugValue because
+  // they are invisible to the store or phi instructions.
+  std::unordered_set<Instruction*> decls_invisible_to_value_assignment_;
 };
 };
 
 
 class SSARewritePass : public MemPass {
 class SSARewritePass : public MemPass {

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

@@ -78,7 +78,7 @@ endif()
 
 
 spvtools_pch(SPIRV_TOOLS_REDUCE_SOURCES pch_source_reduce)
 spvtools_pch(SPIRV_TOOLS_REDUCE_SOURCES pch_source_reduce)
 
 
-add_library(SPIRV-Tools-reduce STATIC ${SPIRV_TOOLS_REDUCE_SOURCES})
+add_library(SPIRV-Tools-reduce ${SPIRV_TOOLS_LIBRARY_TYPE} ${SPIRV_TOOLS_REDUCE_SOURCES})
 
 
 spvtools_default_compile_options(SPIRV-Tools-reduce)
 spvtools_default_compile_options(SPIRV-Tools-reduce)
 target_include_directories(SPIRV-Tools-reduce
 target_include_directories(SPIRV-Tools-reduce
@@ -90,7 +90,7 @@ target_include_directories(SPIRV-Tools-reduce
 )
 )
 # The reducer reuses a lot of functionality from the SPIRV-Tools library.
 # The reducer reuses a lot of functionality from the SPIRV-Tools library.
 target_link_libraries(SPIRV-Tools-reduce
 target_link_libraries(SPIRV-Tools-reduce
-  PUBLIC ${SPIRV_TOOLS}-static
+  PUBLIC ${SPIRV_TOOLS_FULL_VISIBILITY}
   PUBLIC SPIRV-Tools-opt)
   PUBLIC SPIRV-Tools-opt)
 
 
 set_property(TARGET SPIRV-Tools-reduce PROPERTY FOLDER "SPIRV-Tools libraries")
 set_property(TARGET SPIRV-Tools-reduce PROPERTY FOLDER "SPIRV-Tools libraries")

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

@@ -1,4 +1,6 @@
 // Copyright (c) 2017 Google Inc.
 // Copyright (c) 2017 Google Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
 //
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // you may not use this file except in compliance with the License.
@@ -151,7 +153,9 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
         }
         }
 
 
         if (spvIsVulkanEnv(_.context()->target_env) &&
         if (spvIsVulkanEnv(_.context()->target_env) &&
-            _.GetBitWidth(result_type) != 32) {
+            (_.GetBitWidth(result_type) != 32 &&
+             (_.GetBitWidth(result_type) != 64 ||
+              !_.HasCapability(SpvCapabilityInt64ImageEXT)))) {
           switch (opcode) {
           switch (opcode) {
             case SpvOpAtomicSMin:
             case SpvOpAtomicSMin:
             case SpvOpAtomicUMin:
             case SpvOpAtomicUMin:

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

@@ -1,4 +1,6 @@
 // Copyright (c) 2018 Google LLC.
 // Copyright (c) 2018 Google LLC.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
 //
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // you may not use this file except in compliance with the License.
@@ -14,8 +16,6 @@
 
 
 // Validates correctness of built-in variables.
 // Validates correctness of built-in variables.
 
 
-#include "source/val/validate.h"
-
 #include <functional>
 #include <functional>
 #include <list>
 #include <list>
 #include <map>
 #include <map>
@@ -31,6 +31,7 @@
 #include "source/spirv_target_env.h"
 #include "source/spirv_target_env.h"
 #include "source/util/bitutils.h"
 #include "source/util/bitutils.h"
 #include "source/val/instruction.h"
 #include "source/val/instruction.h"
+#include "source/val/validate.h"
 #include "source/val/validation_state.h"
 #include "source/val/validation_state.h"
 
 
 namespace spvtools {
 namespace spvtools {
@@ -230,6 +231,12 @@ class BuiltInsValidator {
   spv_result_t ValidateComputeI32InputAtDefinition(const Decoration& decoration,
   spv_result_t ValidateComputeI32InputAtDefinition(const Decoration& decoration,
                                                    const Instruction& inst);
                                                    const Instruction& inst);
 
 
+  spv_result_t ValidatePrimitiveShadingRateAtDefinition(
+      const Decoration& decoration, const Instruction& inst);
+
+  spv_result_t ValidateShadingRateAtDefinition(const Decoration& decoration,
+                                               const Instruction& inst);
+
   // The following section contains functions which are called when id defined
   // The following section contains functions which are called when id defined
   // by |referenced_inst| is
   // by |referenced_inst| is
   // 1. referenced by |referenced_from_inst|
   // 1. referenced by |referenced_from_inst|
@@ -383,6 +390,16 @@ class BuiltInsValidator {
       const Instruction& referenced_inst,
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
       const Instruction& referenced_from_inst);
 
 
+  spv_result_t ValidatePrimitiveShadingRateAtReference(
+      const Decoration& decoration, const Instruction& built_in_inst,
+      const Instruction& referenced_inst,
+      const Instruction& referenced_from_inst);
+
+  spv_result_t ValidateShadingRateAtReference(
+      const Decoration& decoration, const Instruction& built_in_inst,
+      const Instruction& referenced_inst,
+      const Instruction& referenced_from_inst);
+
   // Validates that |built_in_inst| is not (even indirectly) referenced from
   // Validates that |built_in_inst| is not (even indirectly) referenced from
   // within a function which can be called with |execution_model|.
   // within a function which can be called with |execution_model|.
   //
   //
@@ -2623,12 +2640,26 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference(
         case SpvExecutionModelVertex:
         case SpvExecutionModelVertex:
         case SpvExecutionModelTessellationEvaluation: {
         case SpvExecutionModelTessellationEvaluation: {
           if (!_.HasCapability(SpvCapabilityShaderViewportIndexLayerEXT)) {
           if (!_.HasCapability(SpvCapabilityShaderViewportIndexLayerEXT)) {
+            if (operand == SpvBuiltInViewportIndex &&
+                _.HasCapability(SpvCapabilityShaderViewportIndex))
+              break;  // Ok
+            if (operand == SpvBuiltInLayer &&
+                _.HasCapability(SpvCapabilityShaderLayer))
+              break;  // Ok
+
+            const char* capability = "ShaderViewportIndexLayerEXT";
+
+            if (operand == SpvBuiltInViewportIndex)
+              capability = "ShaderViewportIndexLayerEXT or ShaderViewportIndex";
+            if (operand == SpvBuiltInLayer)
+              capability = "ShaderViewportIndexLayerEXT or ShaderLayer";
+
             return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
             return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                    << "Using BuiltIn "
                    << "Using BuiltIn "
                    << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
                    << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
                                                     operand)
                                                     operand)
-                   << " in Vertex or Tessellation execution model requires "
-                      "the ShaderViewportIndexLayerEXT capability.";
+                   << " in Vertex or Tessellation execution model requires the "
+                   << capability << " capability.";
           }
           }
           break;
           break;
         }
         }
@@ -3314,6 +3345,142 @@ spv_result_t BuiltInsValidator::ValidateSMBuiltinsAtReference(
   return SPV_SUCCESS;
   return SPV_SUCCESS;
 }
 }
 
 
+spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtDefinition(
+    const Decoration& decoration, const Instruction& inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if (spv_result_t error = ValidateI32(
+            decoration, inst,
+            [this, &inst,
+             &decoration](const std::string& message) -> spv_result_t {
+              return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4486)
+                     << "According to the Vulkan spec BuiltIn "
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                      decoration.params()[0])
+                     << " variable needs to be a 32-bit int scalar. "
+                     << message;
+            })) {
+      return error;
+    }
+  }
+
+  // Seed at reference checks with this built-in.
+  return ValidatePrimitiveShadingRateAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtReference(
+    const Decoration& decoration, const Instruction& built_in_inst,
+    const Instruction& referenced_inst,
+    const Instruction& referenced_from_inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != SpvStorageClassMax &&
+        storage_class != SpvStorageClassOutput) {
+      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4485) << "Vulkan spec allows BuiltIn "
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                              decoration.params()[0])
+             << " to be only used for variables with Output storage class. "
+             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                 referenced_from_inst)
+             << " " << GetStorageClassDesc(referenced_from_inst);
+    }
+
+    for (const SpvExecutionModel execution_model : execution_models_) {
+      switch (execution_model) {
+        case SpvExecutionModelVertex:
+        case SpvExecutionModelGeometry:
+        case SpvExecutionModelMeshNV:
+          break;
+        default: {
+          return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+                 << _.VkErrorID(4484) << "Vulkan spec allows BuiltIn "
+                 << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                  decoration.params()[0])
+                 << " to be used only with Vertex, Geometry, or MeshNV "
+                    "execution models. "
+                 << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                     referenced_from_inst, execution_model);
+        }
+      }
+    }
+  }
+
+  if (function_id_ == 0) {
+    // Propagate this rule to all dependant ids in the global scope.
+    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
+        std::bind(&BuiltInsValidator::ValidatePrimitiveShadingRateAtReference,
+                  this, decoration, built_in_inst, referenced_from_inst,
+                  std::placeholders::_1));
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t BuiltInsValidator::ValidateShadingRateAtDefinition(
+    const Decoration& decoration, const Instruction& inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if (spv_result_t error = ValidateI32(
+            decoration, inst,
+            [this, &inst,
+             &decoration](const std::string& message) -> spv_result_t {
+              return _.diag(SPV_ERROR_INVALID_DATA, &inst)
+                     << _.VkErrorID(4492)
+                     << "According to the Vulkan spec BuiltIn "
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                      decoration.params()[0])
+                     << " variable needs to be a 32-bit int scalar. "
+                     << message;
+            })) {
+      return error;
+    }
+  }
+
+  // Seed at reference checks with this built-in.
+  return ValidateShadingRateAtReference(decoration, inst, inst, inst);
+}
+
+spv_result_t BuiltInsValidator::ValidateShadingRateAtReference(
+    const Decoration& decoration, const Instruction& built_in_inst,
+    const Instruction& referenced_inst,
+    const Instruction& referenced_from_inst) {
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != SpvStorageClassMax &&
+        storage_class != SpvStorageClassInput) {
+      return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+             << _.VkErrorID(4491) << "Vulkan spec allows BuiltIn "
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                              decoration.params()[0])
+             << " to be only used for variables with Input storage class. "
+             << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                 referenced_from_inst)
+             << " " << GetStorageClassDesc(referenced_from_inst);
+    }
+
+    for (const SpvExecutionModel execution_model : execution_models_) {
+      if (execution_model != SpvExecutionModelFragment) {
+        return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
+               << _.VkErrorID(4490) << "Vulkan spec allows BuiltIn "
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
+                                                decoration.params()[0])
+               << " to be used only with the Fragment execution model. "
+               << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
+                                   referenced_from_inst, execution_model);
+      }
+    }
+  }
+
+  if (function_id_ == 0) {
+    // Propagate this rule to all dependant ids in the global scope.
+    id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
+        &BuiltInsValidator::ValidateShadingRateAtReference, this, decoration,
+        built_in_inst, referenced_from_inst, std::placeholders::_1));
+  }
+
+  return SPV_SUCCESS;
+}
+
 spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
 spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
     const Decoration& decoration, const Instruction& inst) {
   const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]);
   const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]);
@@ -3514,6 +3681,11 @@ spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
     case SpvBuiltInRayGeometryIndexKHR: {
     case SpvBuiltInRayGeometryIndexKHR: {
       // No validation rules (for the moment).
       // No validation rules (for the moment).
       break;
       break;
+
+      case SpvBuiltInPrimitiveShadingRateKHR:
+        return ValidatePrimitiveShadingRateAtDefinition(decoration, inst);
+      case SpvBuiltInShadingRateKHR:
+        return ValidateShadingRateAtDefinition(decoration, inst);
     }
     }
   }
   }
   return SPV_SUCCESS;
   return SPV_SUCCESS;

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

@@ -89,6 +89,8 @@ spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) {
            << block->predecessors()->size() << ").";
            << block->predecessors()->size() << ").";
   }
   }
 
 
+  std::unordered_set<uint32_t> observed_predecessors;
+
   for (size_t i = 3; i < inst->words().size(); ++i) {
   for (size_t i = 3; i < inst->words().size(); ++i) {
     auto inc_id = inst->word(i);
     auto inc_id = inst->word(i);
     if (i % 2 == 1) {
     if (i % 2 == 1) {
@@ -115,6 +117,17 @@ spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) {
                << " is not a predecessor of <id> " << _.getIdName(block->id())
                << " is not a predecessor of <id> " << _.getIdName(block->id())
                << ".";
                << ".";
       }
       }
+
+      // We must not have already seen this predecessor as one of the phi's
+      // operands.
+      if (observed_predecessors.count(inc_id) != 0) {
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
+               << "OpPhi references incoming basic block <id> "
+               << _.getIdName(inc_id) << " multiple times.";
+      }
+
+      // Note the fact that we have now observed this predecessor.
+      observed_predecessors.insert(inc_id);
     }
     }
   }
   }
 
 

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

@@ -1,4 +1,6 @@
 // Copyright (c) 2017 Google Inc.
 // Copyright (c) 2017 Google Inc.
+// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
+// reserved.
 //
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // you may not use this file except in compliance with the License.
@@ -737,7 +739,9 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
     if ((!_.IsFloatScalarType(info.sampled_type) &&
     if ((!_.IsFloatScalarType(info.sampled_type) &&
          !_.IsIntScalarType(info.sampled_type)) ||
          !_.IsIntScalarType(info.sampled_type)) ||
-        32 != _.GetBitWidth(info.sampled_type)) {
+        (32 != _.GetBitWidth(info.sampled_type) &&
+         (64 != _.GetBitWidth(info.sampled_type) ||
+          !_.HasCapability(SpvCapabilityInt64ImageEXT)))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Sampled Type to be a 32-bit int or float "
              << "Expected Sampled Type to be a 32-bit int or float "
                 "scalar type for Vulkan environment";
                 "scalar type for Vulkan environment";

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff