Răsfoiți Sursa

Updated spirv-tools.

Бранимир Караџић 2 ani în urmă
părinte
comite
1097abfc57
24 a modificat fișierele cu 814 adăugiri și 133 ștergeri
  1. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  2. 8 0
      3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
  3. 4 0
      3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
  4. 2 0
      3rdparty/spirv-tools/include/generated/extension_enum.inc
  5. 18 1
      3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
  6. 48 31
      3rdparty/spirv-tools/include/spirv-tools/instrument.hpp
  7. 32 24
      3rdparty/spirv-tools/source/opt/const_folding_rules.cpp
  8. 544 37
      3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.cpp
  9. 21 8
      3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.h
  10. 18 0
      3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.cpp
  11. 3 0
      3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h
  12. 13 0
      3rdparty/spirv-tools/source/opt/instrument_pass.cpp
  13. 3 2
      3rdparty/spirv-tools/source/opt/instrument_pass.h
  14. 8 1
      3rdparty/spirv-tools/source/opt/ir_builder.h
  15. 1 1
      3rdparty/spirv-tools/source/opt/licm_pass.cpp
  16. 9 14
      3rdparty/spirv-tools/source/opt/loop_descriptor.cpp
  17. 4 4
      3rdparty/spirv-tools/source/opt/loop_descriptor.h
  18. 11 5
      3rdparty/spirv-tools/source/util/small_vector.h
  19. 4 2
      3rdparty/spirv-tools/source/val/validate_annotation.cpp
  20. 1 1
      3rdparty/spirv-tools/source/val/validate_constants.cpp
  21. 1 0
      3rdparty/spirv-tools/source/val/validate_function.cpp
  22. 56 1
      3rdparty/spirv-tools/source/val/validate_image.cpp
  23. 3 0
      3rdparty/spirv-tools/source/val/validate_mode_setting.cpp
  24. 1 0
      3rdparty/spirv-tools/source/val/validation_state.cpp

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

@@ -1 +1 @@
-"v2023.2", "SPIRV-Tools v2023.2 v2022.4-165-g574d9da4"
+"v2023.2", "SPIRV-Tools v2023.2 v2022.4-192-ge472626b"

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

@@ -50,6 +50,7 @@ static const spv::Capability pygen_variable_caps_NamedBarrier[] = {spv::Capabili
 static const spv::Capability pygen_variable_caps_PipeStorage[] = {spv::Capability::PipeStorage};
 static const spv::Capability pygen_variable_caps_Pipes[] = {spv::Capability::Pipes};
 static const spv::Capability pygen_variable_caps_RayQueryKHR[] = {spv::Capability::RayQueryKHR};
+static const spv::Capability pygen_variable_caps_RayQueryPositionFetchKHR[] = {spv::Capability::RayQueryPositionFetchKHR};
 static const spv::Capability pygen_variable_caps_RayTracingKHR[] = {spv::Capability::RayTracingKHR};
 static const spv::Capability pygen_variable_caps_RayTracingKHRRayQueryKHR[] = {spv::Capability::RayTracingKHR, spv::Capability::RayQueryKHR};
 static const spv::Capability pygen_variable_caps_RayTracingMotionBlurNV[] = {spv::Capability::RayTracingMotionBlurNV};
@@ -76,6 +77,9 @@ static const spv::Capability pygen_variable_caps_SubgroupVoteKHR[] = {spv::Capab
 static const spv::Capability pygen_variable_caps_TextureBlockMatchQCOM[] = {spv::Capability::TextureBlockMatchQCOM};
 static const spv::Capability pygen_variable_caps_TextureBoxFilterQCOM[] = {spv::Capability::TextureBoxFilterQCOM};
 static const spv::Capability pygen_variable_caps_TextureSampleWeightedQCOM[] = {spv::Capability::TextureSampleWeightedQCOM};
+static const spv::Capability pygen_variable_caps_TileImageColorReadAccessEXT[] = {spv::Capability::TileImageColorReadAccessEXT};
+static const spv::Capability pygen_variable_caps_TileImageDepthReadAccessEXT[] = {spv::Capability::TileImageDepthReadAccessEXT};
+static const spv::Capability pygen_variable_caps_TileImageStencilReadAccessEXT[] = {spv::Capability::TileImageStencilReadAccessEXT};
 static const spv::Capability pygen_variable_caps_USMStorageClassesINTEL[] = {spv::Capability::USMStorageClassesINTEL};
 static const spv::Capability pygen_variable_caps_UnstructuredLoopControlsINTEL[] = {spv::Capability::UnstructuredLoopControlsINTEL};
 static const spv::Capability pygen_variable_caps_VariableLengthArrayINTEL[] = {spv::Capability::VariableLengthArrayINTEL};
@@ -455,6 +459,9 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"PtrEqual", spv::Op::OpPtrEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"PtrNotEqual", spv::Op::OpPtrNotEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
   {"PtrDiff", spv::Op::OpPtrDiff, 3, pygen_variable_caps_AddressesVariablePointersVariablePointersStorageBuffer, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
+  {"ColorAttachmentReadEXT", spv::Op::OpColorAttachmentReadEXT, 1, pygen_variable_caps_TileImageColorReadAccessEXT, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"DepthAttachmentReadEXT", spv::Op::OpDepthAttachmentReadEXT, 1, pygen_variable_caps_TileImageDepthReadAccessEXT, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"StencilAttachmentReadEXT", spv::Op::OpStencilAttachmentReadEXT, 1, pygen_variable_caps_TileImageStencilReadAccessEXT, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"TerminateInvocation", spv::Op::OpTerminateInvocation, 1, pygen_variable_caps_Shader, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_KHR_terminate_invocation, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
   {"SubgroupBallotKHR", spv::Op::OpSubgroupBallotKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu, 0xffffffffu},
   {"SubgroupFirstInvocationKHR", spv::Op::OpSubgroupFirstInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu, 0xffffffffu},
@@ -547,6 +554,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"TraceNV", spv::Op::OpTraceNV, 1, pygen_variable_caps_RayTracingNV, 11, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu},
   {"TraceMotionNV", spv::Op::OpTraceMotionNV, 1, pygen_variable_caps_RayTracingMotionBlurNV, 12, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing_motion_blur, 0xffffffffu, 0xffffffffu},
   {"TraceRayMotionNV", spv::Op::OpTraceRayMotionNV, 1, pygen_variable_caps_RayTracingMotionBlurNV, 12, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing_motion_blur, 0xffffffffu, 0xffffffffu},
+  {"RayQueryGetIntersectionTriangleVertexPositionsKHR", spv::Op::OpRayQueryGetIntersectionTriangleVertexPositionsKHR, 1, pygen_variable_caps_RayQueryPositionFetchKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"TypeAccelerationStructureKHR", spv::Op::OpTypeAccelerationStructureKHR, 3, pygen_variable_caps_RayTracingNVRayTracingKHRRayQueryKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 3, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracingSPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
   {"TypeAccelerationStructureNV", spv::Op::OpTypeAccelerationStructureNV, 3, pygen_variable_caps_RayTracingNVRayTracingKHRRayQueryKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 3, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracingSPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
   {"ExecuteCallableNV", spv::Op::OpExecuteCallableNV, 1, pygen_variable_caps_RayTracingNV, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_ray_tracing, 0xffffffffu, 0xffffffffu},

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

@@ -23,6 +23,7 @@ kSPV_EXT_shader_atomic_float_add,
 kSPV_EXT_shader_atomic_float_min_max,
 kSPV_EXT_shader_image_int64,
 kSPV_EXT_shader_stencil_export,
+kSPV_EXT_shader_tile_image,
 kSPV_EXT_shader_viewport_index_layer,
 kSPV_GOOGLE_decorate_string,
 kSPV_GOOGLE_hlsl_functionality1,
@@ -81,6 +82,7 @@ kSPV_KHR_post_depth_coverage,
 kSPV_KHR_ray_cull_mask,
 kSPV_KHR_ray_query,
 kSPV_KHR_ray_tracing,
+kSPV_KHR_ray_tracing_position_fetch,
 kSPV_KHR_shader_atomic_counter_ops,
 kSPV_KHR_shader_ballot,
 kSPV_KHR_shader_clock,

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

@@ -86,6 +86,7 @@ static const spv::Capability pygen_variable_caps_RayTracingMotionBlurNV[] = {spv
 static const spv::Capability pygen_variable_caps_RayTracingNV[] = {spv::Capability::RayTracingNV};
 static const spv::Capability pygen_variable_caps_RayTracingNVRayTracingKHR[] = {spv::Capability::RayTracingNV, spv::Capability::RayTracingKHR};
 static const spv::Capability pygen_variable_caps_RayTracingOpacityMicromapEXT[] = {spv::Capability::RayTracingOpacityMicromapEXT};
+static const spv::Capability pygen_variable_caps_RayTracingPositionFetchKHR[] = {spv::Capability::RayTracingPositionFetchKHR};
 static const spv::Capability pygen_variable_caps_RayTraversalPrimitiveCullingKHR[] = {spv::Capability::RayTraversalPrimitiveCullingKHR};
 static const spv::Capability pygen_variable_caps_RoundToInfinityINTEL[] = {spv::Capability::RoundToInfinityINTEL};
 static const spv::Capability pygen_variable_caps_RoundingModeRTE[] = {spv::Capability::RoundingModeRTE};
@@ -119,6 +120,9 @@ static const spv::Capability pygen_variable_caps_StorageImageExtendedFormats[] =
 static const spv::Capability pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot[] = {spv::Capability::SubgroupBallotKHR, spv::Capability::GroupNonUniformBallot};
 static const spv::Capability pygen_variable_caps_SubgroupDispatch[] = {spv::Capability::SubgroupDispatch};
 static const spv::Capability pygen_variable_caps_Tessellation[] = {spv::Capability::Tessellation};
+static const spv::Capability pygen_variable_caps_TileImageColorReadAccessEXT[] = {spv::Capability::TileImageColorReadAccessEXT};
+static const spv::Capability pygen_variable_caps_TileImageDepthReadAccessEXT[] = {spv::Capability::TileImageDepthReadAccessEXT};
+static const spv::Capability pygen_variable_caps_TileImageStencilReadAccessEXT[] = {spv::Capability::TileImageStencilReadAccessEXT};
 static const spv::Capability pygen_variable_caps_TransformFeedback[] = {spv::Capability::TransformFeedback};
 static const spv::Capability pygen_variable_caps_USMStorageClassesINTEL[] = {spv::Capability::USMStorageClassesINTEL};
 static const spv::Capability pygen_variable_caps_VariablePointersStorageBuffer[] = {spv::Capability::VariablePointersStorageBuffer};
@@ -151,6 +155,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float
 static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_min_max[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_min_max};
 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_tile_image[] = {spvtools::Extension::kSPV_EXT_shader_tile_image};
 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_user_type[] = {spvtools::Extension::kSPV_GOOGLE_user_type};
@@ -208,6 +213,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvt
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_querySPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_query, spvtools::Extension::kSPV_KHR_ray_tracing};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing, spvtools::Extension::kSPV_NV_ray_tracing};
+static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracing_position_fetch[] = {spvtools::Extension::kSPV_KHR_ray_tracing_position_fetch};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_atomic_counter_ops[] = {spvtools::Extension::kSPV_KHR_shader_atomic_counter_ops};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock};
@@ -468,6 +474,9 @@ static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = {
   {"SubgroupsPerWorkgroupId", 37, 1, pygen_variable_caps_SubgroupDispatch, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2), 0xffffffffu},
   {"LocalSizeId", 38, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2), 0xffffffffu},
   {"LocalSizeHintId", 39, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2), 0xffffffffu},
+  {"NonCoherentColorAttachmentReadEXT", 4169, 1, pygen_variable_caps_TileImageColorReadAccessEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"NonCoherentDepthAttachmentReadEXT", 4170, 1, pygen_variable_caps_TileImageDepthReadAccessEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"NonCoherentStencilAttachmentReadEXT", 4171, 1, pygen_variable_caps_TileImageStencilReadAccessEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupUniformControlFlowKHR", 4421, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_subgroup_uniform_control_flow, {}, 0xffffffffu, 0xffffffffu},
   {"PostDepthCoverage", 4446, 1, pygen_variable_caps_SampleMaskPostDepthCoverage, 1, pygen_variable_exts_SPV_KHR_post_depth_coverage, {}, 0xffffffffu, 0xffffffffu},
   {"DenormPreserve", 4459, 1, pygen_variable_caps_DenormPreserve, 1, pygen_variable_exts_SPV_KHR_float_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
@@ -526,6 +535,7 @@ static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = {
   {"AtomicCounter", 10, 1, pygen_variable_caps_AtomicStorage, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Image", 11, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"StorageBuffer", 12, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_KHR_storage_buffer_storage_classSPV_KHR_variable_pointers, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
+  {"TileImageEXT", 4172, 1, pygen_variable_caps_TileImageColorReadAccessEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
   {"CallableDataNV", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"CallableDataKHR", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"IncomingCallableDataNV", 5329, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
@@ -554,7 +564,8 @@ static const spv_operand_desc_t pygen_variable_DimEntries[] = {
   {"Cube", 3, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Rect", 4, 1, pygen_variable_caps_SampledRect, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
   {"Buffer", 5, 1, pygen_variable_caps_SampledBuffer, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
-  {"SubpassData", 6, 1, pygen_variable_caps_InputAttachment, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
+  {"SubpassData", 6, 1, pygen_variable_caps_InputAttachment, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
+  {"TileImageDataEXT", 4173, 1, pygen_variable_caps_TileImageColorReadAccessEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_SamplerAddressingModeEntries[] = {
@@ -974,6 +985,7 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
   {"HitKindNV", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"HitKindKHR", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"CurrentRayTimeNV", 5334, 1, pygen_variable_caps_RayTracingMotionBlurNV, 1, pygen_variable_exts_SPV_NV_ray_tracing_motion_blur, {}, 0xffffffffu, 0xffffffffu},
+  {"HitTriangleVertexPositionsKHR", 5335, 1, pygen_variable_caps_RayTracingPositionFetchKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
   {"IncomingRayFlagsNV", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"IncomingRayFlagsKHR", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"RayGeometryIndexKHR", 5352, 1, pygen_variable_caps_RayTracingKHR, 1, pygen_variable_exts_SPV_KHR_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
@@ -1083,6 +1095,9 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"ShaderViewportIndex", 70, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"UniformDecoration", 71, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
   {"CoreBuiltinsARM", 4165, 0, nullptr, 1, pygen_variable_exts_SPV_ARM_core_builtins, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
+  {"TileImageColorReadAccessEXT", 4166, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu},
+  {"TileImageDepthReadAccessEXT", 4167, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu},
+  {"TileImageStencilReadAccessEXT", 4168, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 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},
   {"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
@@ -1165,6 +1180,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"UniformTexelBufferArrayNonUniformIndexingEXT", 5311, 2, pygen_variable_caps_SampledBufferShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"StorageTexelBufferArrayNonUniformIndexing", 5312, 2, pygen_variable_caps_ImageBufferShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
   {"StorageTexelBufferArrayNonUniformIndexingEXT", 5312, 2, pygen_variable_caps_ImageBufferShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
+  {"RayTracingPositionFetchKHR", 5336, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_ray_tracing_position_fetch, {}, 0xffffffffu, 0xffffffffu},
   {"RayTracingNV", 5340, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
   {"RayTracingMotionBlurNV", 5341, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_NV_ray_tracing_motion_blur, {}, 0xffffffffu, 0xffffffffu},
   {"VulkanMemoryModel", 5345, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_vulkan_memory_model, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
@@ -1185,6 +1201,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"RayTracingOpacityMicromapEXT", 5381, 2, pygen_variable_caps_RayQueryKHRRayTracingKHR, 1, pygen_variable_exts_SPV_EXT_opacity_micromap, {}, 0xffffffffu, 0xffffffffu},
   {"ShaderInvocationReorderNV", 5383, 1, pygen_variable_caps_RayTracingKHR, 1, pygen_variable_exts_SPV_NV_shader_invocation_reorder, {}, 0xffffffffu, 0xffffffffu},
   {"BindlessTextureNV", 5390, 0, nullptr, 1, pygen_variable_exts_SPV_NV_bindless_texture, {}, 0xffffffffu, 0xffffffffu},
+  {"RayQueryPositionFetchKHR", 5391, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_ray_tracing_position_fetch, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupShuffleINTEL", 5568, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupBufferBlockIOINTEL", 5569, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupImageBlockIOINTEL", 5570, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},

+ 48 - 31
3rdparty/spirv-tools/include/spirv-tools/instrument.hpp

@@ -146,23 +146,29 @@ static const int kInstValidationOutError = kInstStageOutCnt;
 // about the validation error.
 //
 // A bindless bounds error will output the index and the bound.
-static const int kInstBindlessBoundsOutDescIndex = kInstStageOutCnt + 1;
-static const int kInstBindlessBoundsOutDescBound = kInstStageOutCnt + 2;
-static const int kInstBindlessBoundsOutUnused = kInstStageOutCnt + 3;
-static const int kInstBindlessBoundsOutCnt = kInstStageOutCnt + 4;
+static const int kInstBindlessBoundsOutDescSet = kInstStageOutCnt + 1;
+static const int kInstBindlessBoundsOutDescBinding = kInstStageOutCnt + 2;
+static const int kInstBindlessBoundsOutDescIndex = kInstStageOutCnt + 3;
+static const int kInstBindlessBoundsOutDescBound = kInstStageOutCnt + 4;
+static const int kInstBindlessBoundsOutUnused = kInstStageOutCnt + 5;
+static const int kInstBindlessBoundsOutCnt = kInstStageOutCnt + 6;
 
 // A descriptor uninitialized error will output the index.
-static const int kInstBindlessUninitOutDescIndex = kInstStageOutCnt + 1;
-static const int kInstBindlessUninitOutUnused = kInstStageOutCnt + 2;
-static const int kInstBindlessUninitOutUnused2 = kInstStageOutCnt + 3;
-static const int kInstBindlessUninitOutCnt = kInstStageOutCnt + 4;
+static const int kInstBindlessUninitOutDescSet = kInstStageOutCnt + 1;
+static const int kInstBindlessUninitOutBinding = kInstStageOutCnt + 2;
+static const int kInstBindlessUninitOutDescIndex = kInstStageOutCnt + 3;
+static const int kInstBindlessUninitOutUnused = kInstStageOutCnt + 4;
+static const int kInstBindlessUninitOutUnused2 = kInstStageOutCnt + 5;
+static const int kInstBindlessUninitOutCnt = kInstStageOutCnt + 6;
 
 // A buffer out-of-bounds error will output the descriptor
 // index, the buffer offset and the buffer size
-static const int kInstBindlessBuffOOBOutDescIndex = kInstStageOutCnt + 1;
-static const int kInstBindlessBuffOOBOutBuffOff = kInstStageOutCnt + 2;
-static const int kInstBindlessBuffOOBOutBuffSize = kInstStageOutCnt + 3;
-static const int kInstBindlessBuffOOBOutCnt = kInstStageOutCnt + 4;
+static const int kInstBindlessBuffOOBOutDescSet = kInstStageOutCnt + 1;
+static const int kInstBindlessBuffOOBOutDescBinding = kInstStageOutCnt + 2;
+static const int kInstBindlessBuffOOBOutDescIndex = kInstStageOutCnt + 3;
+static const int kInstBindlessBuffOOBOutBuffOff = kInstStageOutCnt + 4;
+static const int kInstBindlessBuffOOBOutBuffSize = kInstStageOutCnt + 5;
+static const int kInstBindlessBuffOOBOutCnt = kInstStageOutCnt + 6;
 
 // A buffer address unalloc error will output the 64-bit pointer in
 // two 32-bit pieces, lower bits first.
@@ -171,7 +177,7 @@ static const int kInstBuffAddrUnallocOutDescPtrHi = kInstStageOutCnt + 2;
 static const int kInstBuffAddrUnallocOutCnt = kInstStageOutCnt + 3;
 
 // Maximum Output Record Member Count
-static const int kInstMaxOutCnt = kInstStageOutCnt + 4;
+static const int kInstMaxOutCnt = kInstStageOutCnt + 6;
 
 // Validation Error Codes
 //
@@ -217,26 +223,37 @@ static const int kDebugInputBindingBuffAddr = 2;
 // This is the output buffer written by InstDebugPrintfPass.
 static const int kDebugOutputPrintfStream = 3;
 
+// clang-format off
 // Bindless Validation Input Buffer Format
 //
-// An input buffer for bindless validation consists of a single array of
-// unsigned integers we will call Data[]. This array is formatted as follows.
-//
-// At offset kDebugInputBindlessInitOffset in Data[] is a single uint which
-// gives an offset to the start of the bindless initialization data. More
-// specifically, if the following value is zero, we know that the descriptor at
-// (set = s, binding = b, index = i) is not initialized; if the value is
-// non-zero, and the descriptor points to a buffer, the value is the length of
-// the buffer in bytes and can be used to check for out-of-bounds buffer
-// references:
-// Data[ i + Data[ b + Data[ s + Data[ kDebugInputBindlessInitOffset ] ] ] ]
-static const int kDebugInputBindlessInitOffset = 0;
-
-// At offset kDebugInputBindlessOffsetLengths is some number of uints which
-// provide the bindless length data. More specifically, the number of
-// descriptors at (set=s, binding=b) is:
-// Data[ Data[ s + kDebugInputBindlessOffsetLengths ] + b ]
-static const int kDebugInputBindlessOffsetLengths = 1;
+// An input buffer for bindless validation has this structure:
+// GLSL:
+// layout(buffer_reference, std430, buffer_reference_align = 8) buffer DescriptorSetData {
+//     uint num_bindings;
+//     uint data[];
+// };
+//
+// layout(set = 7, binding = 1, std430) buffer inst_bindless_InputBuffer
+// {
+//     DescriptorSetData desc_sets[32];
+// } inst_bindless_input_buffer;
+//
+//
+// To look up the length of a binding:
+//   uint length = inst_bindless_input_buffer[set].data[binding];
+// Scalar bindings have a length of 1.
+//
+// To look up the initialization state of a descriptor in a binding:
+//   uint num_bindings = inst_bindless_input_buffer[set].num_bindings;
+//   uint binding_state_start = inst_bindless_input_buffer[set].data[num_bindings + binding];
+//   uint init_state = inst_bindless_input_buffer[set].data[binding_state_start + index];
+//
+// For scalar bindings, use 0 for the index.
+// clang-format on
+//
+// The size of the inst_bindless_input_buffer array, regardless of how many
+// descriptor sets the device supports.
+static const int kDebugInputBindlessMaxDescSets = 32;
 
 // Buffer Device Address Input Buffer Format
 //

+ 32 - 24
3rdparty/spirv-tools/source/opt/const_folding_rules.cpp

@@ -398,12 +398,14 @@ ConstantFoldingRule FoldVectorTimesMatrix() {
     if (float_type->width() == 32) {
       for (uint32_t i = 0; i < resultVectorSize; ++i) {
         float result_scalar = 0.0f;
-        const analysis::VectorConstant* c2_vec =
-            c2_components[i]->AsVectorConstant();
-        for (uint32_t j = 0; j < c2_vec->GetComponents().size(); ++j) {
-          float c1_scalar = c1_components[j]->GetFloat();
-          float c2_scalar = c2_vec->GetComponents()[j]->GetFloat();
-          result_scalar += c1_scalar * c2_scalar;
+        if (!c2_components[i]->AsNullConstant()) {
+          const analysis::VectorConstant* c2_vec =
+              c2_components[i]->AsVectorConstant();
+          for (uint32_t j = 0; j < c2_vec->GetComponents().size(); ++j) {
+            float c1_scalar = c1_components[j]->GetFloat();
+            float c2_scalar = c2_vec->GetComponents()[j]->GetFloat();
+            result_scalar += c1_scalar * c2_scalar;
+          }
         }
         utils::FloatProxy<float> result(result_scalar);
         std::vector<uint32_t> words = result.GetWords();
@@ -415,12 +417,14 @@ ConstantFoldingRule FoldVectorTimesMatrix() {
     } else if (float_type->width() == 64) {
       for (uint32_t i = 0; i < c2_components.size(); ++i) {
         double result_scalar = 0.0;
-        const analysis::VectorConstant* c2_vec =
-            c2_components[i]->AsVectorConstant();
-        for (uint32_t j = 0; j < c2_vec->GetComponents().size(); ++j) {
-          double c1_scalar = c1_components[j]->GetDouble();
-          double c2_scalar = c2_vec->GetComponents()[j]->GetDouble();
-          result_scalar += c1_scalar * c2_scalar;
+        if (!c2_components[i]->AsNullConstant()) {
+          const analysis::VectorConstant* c2_vec =
+              c2_components[i]->AsVectorConstant();
+          for (uint32_t j = 0; j < c2_vec->GetComponents().size(); ++j) {
+            double c1_scalar = c1_components[j]->GetDouble();
+            double c2_scalar = c2_vec->GetComponents()[j]->GetDouble();
+            result_scalar += c1_scalar * c2_scalar;
+          }
         }
         utils::FloatProxy<double> result(result_scalar);
         std::vector<uint32_t> words = result.GetWords();
@@ -491,12 +495,14 @@ ConstantFoldingRule FoldMatrixTimesVector() {
       for (uint32_t i = 0; i < resultVectorSize; ++i) {
         float result_scalar = 0.0f;
         for (uint32_t j = 0; j < c1_components.size(); ++j) {
-          float c1_scalar = c1_components[j]
-                                ->AsVectorConstant()
-                                ->GetComponents()[i]
-                                ->GetFloat();
-          float c2_scalar = c2_components[j]->GetFloat();
-          result_scalar += c1_scalar * c2_scalar;
+          if (!c1_components[j]->AsNullConstant()) {
+            float c1_scalar = c1_components[j]
+                                  ->AsVectorConstant()
+                                  ->GetComponents()[i]
+                                  ->GetFloat();
+            float c2_scalar = c2_components[j]->GetFloat();
+            result_scalar += c1_scalar * c2_scalar;
+          }
         }
         utils::FloatProxy<float> result(result_scalar);
         std::vector<uint32_t> words = result.GetWords();
@@ -509,12 +515,14 @@ ConstantFoldingRule FoldMatrixTimesVector() {
       for (uint32_t i = 0; i < resultVectorSize; ++i) {
         double result_scalar = 0.0;
         for (uint32_t j = 0; j < c1_components.size(); ++j) {
-          double c1_scalar = c1_components[j]
-                                 ->AsVectorConstant()
-                                 ->GetComponents()[i]
-                                 ->GetDouble();
-          double c2_scalar = c2_components[j]->GetDouble();
-          result_scalar += c1_scalar * c2_scalar;
+          if (!c1_components[j]->AsNullConstant()) {
+            double c1_scalar = c1_components[j]
+                                   ->AsVectorConstant()
+                                   ->GetComponents()[i]
+                                   ->GetDouble();
+            double c2_scalar = c2_components[j]->GetDouble();
+            result_scalar += c1_scalar * c2_scalar;
+          }
         }
         utils::FloatProxy<double> result(result_scalar);
         std::vector<uint32_t> words = result.GetWords();

+ 544 - 37
3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.cpp

@@ -16,6 +16,8 @@
 
 #include "inst_bindless_check_pass.h"
 
+#include "source/spirv_constant.h"
+
 namespace spvtools {
 namespace opt {
 namespace {
@@ -40,37 +42,521 @@ constexpr int kSpvTypeImageMS = 4;
 constexpr int kSpvTypeImageSampled = 5;
 }  // namespace
 
+void InstBindlessCheckPass::SetupInputBufferIds() {
+  if (input_buffer_id_ != 0) {
+    return;
+  }
+  AddStorageBufferExt();
+  if (!get_feature_mgr()->HasExtension(kSPV_KHR_physical_storage_buffer)) {
+    context()->AddExtension("SPV_KHR_physical_storage_buffer");
+  }
+  context()->AddCapability(spv::Capability::PhysicalStorageBufferAddresses);
+  Instruction* memory_model = get_module()->GetMemoryModel();
+  // TODO should this be just Physical64?
+  memory_model->SetInOperand(
+      0u, {uint32_t(spv::AddressingModel::PhysicalStorageBuffer64)});
+
+  analysis::DecorationManager* deco_mgr = get_decoration_mgr();
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  constexpr uint32_t width = 32u;
+
+  // declare the DescriptorSetData struct
+  analysis::Struct* desc_set_struct =
+      GetStruct({type_mgr->GetUIntType(), GetUintRuntimeArrayType(width)});
+  desc_set_type_id_ = type_mgr->GetTypeInstruction(desc_set_struct);
+  // By the Vulkan spec, a pre-existing struct containing a RuntimeArray
+  // must be a block, and will therefore be decorated with Block. Therefore
+  // the undecorated type returned here will not be pre-existing and can
+  // safely be decorated. Since this type is now decorated, it is out of
+  // sync with the TypeManager and therefore the TypeManager must be
+  // invalidated after this pass.
+  assert(context()->get_def_use_mgr()->NumUses(desc_set_type_id_) == 0 &&
+         "used struct type returned");
+  deco_mgr->AddDecoration(desc_set_type_id_, uint32_t(spv::Decoration::Block));
+  deco_mgr->AddMemberDecoration(desc_set_type_id_, 0,
+                                uint32_t(spv::Decoration::Offset), 0);
+  deco_mgr->AddMemberDecoration(desc_set_type_id_, 1,
+                                uint32_t(spv::Decoration::Offset), 4);
+  context()->AddDebug2Inst(
+      NewGlobalName(desc_set_type_id_, "DescriptorSetData"));
+  context()->AddDebug2Inst(NewMemberName(desc_set_type_id_, 0, "num_bindings"));
+  context()->AddDebug2Inst(NewMemberName(desc_set_type_id_, 1, "data"));
+
+  // declare buffer address reference to DescriptorSetData
+  desc_set_ptr_id_ = type_mgr->FindPointerToType(
+      desc_set_type_id_, spv::StorageClass::PhysicalStorageBuffer);
+  // runtime array of buffer addresses
+  analysis::Type* rarr_ty = GetArray(type_mgr->GetType(desc_set_ptr_id_),
+                                     kDebugInputBindlessMaxDescSets);
+  deco_mgr->AddDecorationVal(type_mgr->GetId(rarr_ty),
+                             uint32_t(spv::Decoration::ArrayStride), 8u);
+
+  // declare the InputBuffer type, a struct wrapper around the runtime array
+  analysis::Struct* input_buffer_struct = GetStruct({rarr_ty});
+  input_buffer_struct_id_ = type_mgr->GetTypeInstruction(input_buffer_struct);
+  deco_mgr->AddDecoration(input_buffer_struct_id_,
+                          uint32_t(spv::Decoration::Block));
+  deco_mgr->AddMemberDecoration(input_buffer_struct_id_, 0,
+                                uint32_t(spv::Decoration::Offset), 0);
+  context()->AddDebug2Inst(
+      NewGlobalName(input_buffer_struct_id_, "InputBuffer"));
+  context()->AddDebug2Inst(
+      NewMemberName(input_buffer_struct_id_, 0, "desc_sets"));
+
+  input_buffer_ptr_id_ = type_mgr->FindPointerToType(
+      input_buffer_struct_id_, spv::StorageClass::StorageBuffer);
+
+  // declare the input_buffer global variable
+  input_buffer_id_ = TakeNextId();
+
+  const std::vector<Operand> var_operands = {
+      {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
+       {uint32_t(spv::StorageClass::StorageBuffer)}},
+  };
+  auto new_var_op = spvtools::MakeUnique<Instruction>(
+      context(), spv::Op::OpVariable, input_buffer_ptr_id_, input_buffer_id_,
+      var_operands);
+
+  context()->AddGlobalValue(std::move(new_var_op));
+  context()->AddDebug2Inst(NewGlobalName(input_buffer_id_, "input_buffer"));
+  deco_mgr->AddDecorationVal(
+      input_buffer_id_, uint32_t(spv::Decoration::DescriptorSet), desc_set_);
+  deco_mgr->AddDecorationVal(input_buffer_id_,
+                             uint32_t(spv::Decoration::Binding),
+                             GetInputBufferBinding());
+  if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
+    // Add the new buffer to all entry points.
+    for (auto& entry : get_module()->entry_points()) {
+      entry.AddOperand({SPV_OPERAND_TYPE_ID, {input_buffer_id_}});
+      context()->AnalyzeUses(&entry);
+    }
+  }
+}
+
+// clang-format off
+// GLSL:
+// uint inst_bindless_read_binding_length(uint desc_set_idx, uint binding_idx)
+// {
+//     if (desc_set_idx >= inst_bindless_input_buffer.desc_sets.length()) {
+//         return 0;
+//     }
+//
+//     DescriptorSetData set_data = inst_bindless_input_buffer.desc_sets[desc_set_idx];
+//     uvec2 ptr_as_vec = uvec2(set_data);
+//     if ((ptr_as_vec.x == 0u) && (_ptr_as_vec.y == 0u))
+//     {
+//         return 0u;
+//     }
+//     uint num_bindings = set_data.num_bindings;
+//     if (binding_idx >= num_bindings) {
+//         return 0;
+//     }
+//     return set_data.data[binding_idx];
+// }
+// clang-format on
+uint32_t InstBindlessCheckPass::GenDebugReadLengthFunctionId() {
+  if (read_length_func_id_ != 0) {
+    return read_length_func_id_;
+  }
+  SetupInputBufferIds();
+  const analysis::Integer* uint_type = GetInteger(32, false);
+  const std::vector<const analysis::Type*> param_types(2, uint_type);
+
+  const uint32_t func_id = TakeNextId();
+  std::unique_ptr<Function> func =
+      StartFunction(func_id, uint_type, param_types);
+
+  const std::vector<uint32_t> param_ids = AddParameters(*func, param_types);
+
+  // Create block
+  auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId()));
+  InstructionBuilder builder(
+      context(), new_blk_ptr.get(),
+      IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
+  Instruction* inst;
+
+  inst = builder.AddBinaryOp(
+      GetBoolId(), spv::Op::OpUGreaterThanEqual, param_ids[0],
+      builder.GetUintConstantId(kDebugInputBindlessMaxDescSets));
+  const uint32_t desc_cmp_id = inst->result_id();
+
+  uint32_t error_blk_id = TakeNextId();
+  uint32_t merge_blk_id = TakeNextId();
+  std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
+  std::unique_ptr<Instruction> error_label(NewLabel(error_blk_id));
+  (void)builder.AddConditionalBranch(desc_cmp_id, error_blk_id, merge_blk_id,
+                                     merge_blk_id);
+
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // error return
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                           builder.GetUintConstantId(0));
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // check descriptor set table entry is non-null
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  const uint32_t desc_set_ptr_ptr = type_mgr->FindPointerToType(
+      desc_set_ptr_id_, spv::StorageClass::StorageBuffer);
+
+  inst = builder.AddAccessChain(desc_set_ptr_ptr, input_buffer_id_,
+                                {builder.GetUintConstantId(0), param_ids[0]});
+  const uint32_t set_access_chain_id = inst->result_id();
+
+  inst = builder.AddLoad(desc_set_ptr_id_, set_access_chain_id);
+  const uint32_t desc_set_ptr_id = inst->result_id();
+
+  inst =
+      builder.AddUnaryOp(GetVecUintId(2), spv::Op::OpBitcast, desc_set_ptr_id);
+  const uint32_t ptr_as_uvec_id = inst->result_id();
+
+  inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {0});
+  const uint32_t uvec_x = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_x,
+                             builder.GetUintConstantId(0));
+  const uint32_t x_is_zero_id = inst->result_id();
+
+  inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {1});
+  const uint32_t uvec_y = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_y,
+                             builder.GetUintConstantId(0));
+  const uint32_t y_is_zero_id = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpLogicalAnd, x_is_zero_id,
+                             y_is_zero_id);
+  const uint32_t is_null_id = inst->result_id();
+
+  error_blk_id = TakeNextId();
+  merge_blk_id = TakeNextId();
+  merge_label = NewLabel(merge_blk_id);
+  error_label = NewLabel(error_blk_id);
+  (void)builder.AddConditionalBranch(is_null_id, error_blk_id, merge_blk_id,
+                                     merge_blk_id);
+  func->AddBasicBlock(std::move(new_blk_ptr));
+  // error return
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                           builder.GetUintConstantId(0));
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // check binding is in range
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+
+  const uint32_t uint_ptr = type_mgr->FindPointerToType(
+      GetUintId(), spv::StorageClass::PhysicalStorageBuffer);
+
+  inst = builder.AddAccessChain(uint_ptr, desc_set_ptr_id,
+                                {builder.GetUintConstantId(0)});
+  const uint32_t binding_access_chain_id = inst->result_id();
+
+  inst = builder.AddLoad(GetUintId(), binding_access_chain_id, 8);
+  const uint32_t num_bindings_id = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual,
+                             param_ids[1], num_bindings_id);
+  const uint32_t bindings_cmp_id = inst->result_id();
+
+  error_blk_id = TakeNextId();
+  merge_blk_id = TakeNextId();
+  merge_label = NewLabel(merge_blk_id);
+  error_label = NewLabel(error_blk_id);
+  (void)builder.AddConditionalBranch(bindings_cmp_id, error_blk_id,
+                                     merge_blk_id, merge_blk_id);
+  func->AddBasicBlock(std::move(new_blk_ptr));
+  // error return
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                           builder.GetUintConstantId(0));
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // read binding length
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+
+  inst = builder.AddAccessChain(uint_ptr, desc_set_ptr_id,
+                                {{builder.GetUintConstantId(1), param_ids[1]}});
+  const uint32_t length_ac_id = inst->result_id();
+
+  inst = builder.AddLoad(GetUintId(), length_ac_id, sizeof(uint32_t));
+  const uint32_t length_id = inst->result_id();
+
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, length_id);
+
+  func->AddBasicBlock(std::move(new_blk_ptr));
+  func->SetFunctionEnd(EndFunction());
+
+  context()->AddFunction(std::move(func));
+  context()->AddDebug2Inst(NewGlobalName(func_id, "read_binding_length"));
+
+  read_length_func_id_ = func_id;
+  // Make sure this function doesn't get processed by
+  // InstrumentPass::InstProcessCallTreeFromRoots()
+  param2output_func_id_[2] = func_id;
+  return read_length_func_id_;
+}
+
+// clang-format off
+// GLSL:
+// result = inst_bindless_read_binding_length(desc_set_id, binding_id);
+// clang-format on
 uint32_t InstBindlessCheckPass::GenDebugReadLength(
     uint32_t var_id, InstructionBuilder* builder) {
-  uint32_t desc_set_idx =
-      var2desc_set_[var_id] + kDebugInputBindlessOffsetLengths;
-  uint32_t desc_set_idx_id = builder->GetUintConstantId(desc_set_idx);
-  uint32_t binding_idx_id = builder->GetUintConstantId(var2binding_[var_id]);
-  return GenDebugDirectRead({desc_set_idx_id, binding_idx_id}, builder);
+  const uint32_t func_id = GenDebugReadLengthFunctionId();
+
+  const std::vector<uint32_t> args = {
+      builder->GetUintConstantId(var2desc_set_[var_id]),
+      builder->GetUintConstantId(var2binding_[var_id]),
+  };
+  return GenReadFunctionCall(func_id, args, builder);
+}
+
+// clang-format off
+// GLSL:
+// uint inst_bindless_read_desc_init(uint desc_set_idx, uint binding_idx, uint desc_idx)
+// {
+//     if (desc_set_idx >= uint(inst_bindless_input_buffer.desc_sets.length()))
+//     {
+//         return 0u;
+//     }
+//     DescriptorSetData set_data = inst_bindless_input_buffer.desc_sets[desc_set_idx];
+//     uvec2 ptr_as_vec = uvec2(set_data)
+//     if ((ptr_as_vec .x == 0u) && (ptr_as_vec.y == 0u))
+//     {
+//         return 0u;
+//     }
+//     if (binding_idx >= set_data.num_bindings)
+//     {
+//         return 0u;
+//     }
+//     if (desc_idx >= set_data.data[binding_idx])
+//     {
+//         return 0u;
+//     }
+//     uint desc_records_start = set_data.data[set_data.num_bindings + binding_idx];
+//     return set_data.data[desc_records_start + desc_idx];
+// }
+// clang-format on
+uint32_t InstBindlessCheckPass::GenDebugReadInitFunctionId() {
+  if (read_init_func_id_ != 0) {
+    return read_init_func_id_;
+  }
+  SetupInputBufferIds();
+  const analysis::Integer* uint_type = GetInteger(32, false);
+  const std::vector<const analysis::Type*> param_types(3, uint_type);
+
+  const uint32_t func_id = TakeNextId();
+  std::unique_ptr<Function> func =
+      StartFunction(func_id, uint_type, param_types);
+
+  const std::vector<uint32_t> param_ids = AddParameters(*func, param_types);
+
+  // Create block
+  auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId()));
+  InstructionBuilder builder(
+      context(), new_blk_ptr.get(),
+      IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
+  Instruction* inst;
+
+  inst = builder.AddBinaryOp(
+      GetBoolId(), spv::Op::OpUGreaterThanEqual, param_ids[0],
+      builder.GetUintConstantId(kDebugInputBindlessMaxDescSets));
+  const uint32_t desc_cmp_id = inst->result_id();
+
+  uint32_t error_blk_id = TakeNextId();
+  uint32_t merge_blk_id = TakeNextId();
+  std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
+  std::unique_ptr<Instruction> error_label(NewLabel(error_blk_id));
+  (void)builder.AddConditionalBranch(desc_cmp_id, error_blk_id, merge_blk_id,
+                                     merge_blk_id);
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // error return
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                           builder.GetUintConstantId(0));
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // check descriptor set table entry is non-null
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  const uint32_t desc_set_ptr_ptr = type_mgr->FindPointerToType(
+      desc_set_ptr_id_, spv::StorageClass::StorageBuffer);
+
+  inst = builder.AddAccessChain(desc_set_ptr_ptr, input_buffer_id_,
+                                {builder.GetUintConstantId(0), param_ids[0]});
+  const uint32_t set_access_chain_id = inst->result_id();
+
+  inst = builder.AddLoad(desc_set_ptr_id_, set_access_chain_id);
+  const uint32_t desc_set_ptr_id = inst->result_id();
+
+  inst =
+      builder.AddUnaryOp(GetVecUintId(2), spv::Op::OpBitcast, desc_set_ptr_id);
+  const uint32_t ptr_as_uvec_id = inst->result_id();
+
+  inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {0});
+  const uint32_t uvec_x = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_x,
+                             builder.GetUintConstantId(0));
+  const uint32_t x_is_zero_id = inst->result_id();
+
+  inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {1});
+  const uint32_t uvec_y = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_y,
+                             builder.GetUintConstantId(0));
+  const uint32_t y_is_zero_id = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpLogicalAnd, x_is_zero_id,
+                             y_is_zero_id);
+  const uint32_t is_null_id = inst->result_id();
+
+  error_blk_id = TakeNextId();
+  merge_blk_id = TakeNextId();
+  merge_label = NewLabel(merge_blk_id);
+  error_label = NewLabel(error_blk_id);
+  (void)builder.AddConditionalBranch(is_null_id, error_blk_id, merge_blk_id,
+                                     merge_blk_id);
+  func->AddBasicBlock(std::move(new_blk_ptr));
+  // error return
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                           builder.GetUintConstantId(0));
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // check binding is in range
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+
+  const uint32_t uint_ptr = type_mgr->FindPointerToType(
+      GetUintId(), spv::StorageClass::PhysicalStorageBuffer);
+
+  inst = builder.AddAccessChain(uint_ptr, desc_set_ptr_id,
+                                {builder.GetUintConstantId(0)});
+  const uint32_t binding_access_chain_id = inst->result_id();
+
+  inst = builder.AddLoad(GetUintId(), binding_access_chain_id, 8);
+  const uint32_t num_bindings_id = inst->result_id();
+
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual,
+                             param_ids[1], num_bindings_id);
+  const uint32_t bindings_cmp_id = inst->result_id();
+
+  error_blk_id = TakeNextId();
+  merge_blk_id = TakeNextId();
+  merge_label = NewLabel(merge_blk_id);
+  error_label = NewLabel(error_blk_id);
+  (void)builder.AddConditionalBranch(bindings_cmp_id, error_blk_id,
+                                     merge_blk_id, merge_blk_id);
+  func->AddBasicBlock(std::move(new_blk_ptr));
+  // error return
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                           builder.GetUintConstantId(0));
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // read binding length
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+
+  inst = builder.AddAccessChain(uint_ptr, desc_set_ptr_id,
+                                {{builder.GetUintConstantId(1), param_ids[1]}});
+  const uint32_t length_ac_id = inst->result_id();
+
+  inst = builder.AddLoad(GetUintId(), length_ac_id, sizeof(uint32_t));
+  const uint32_t length_id = inst->result_id();
+
+  // Check descriptor index in bounds
+  inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual,
+                             param_ids[2], length_id);
+  const uint32_t desc_idx_range_id = inst->result_id();
+
+  error_blk_id = TakeNextId();
+  merge_blk_id = TakeNextId();
+  merge_label = NewLabel(merge_blk_id);
+  error_label = NewLabel(error_blk_id);
+  (void)builder.AddConditionalBranch(desc_idx_range_id, error_blk_id,
+                                     merge_blk_id, merge_blk_id);
+  func->AddBasicBlock(std::move(new_blk_ptr));
+  // Error return
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                           builder.GetUintConstantId(0));
+  func->AddBasicBlock(std::move(new_blk_ptr));
+
+  // Read descriptor init status
+  new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
+  builder.SetInsertPoint(&*new_blk_ptr);
+
+  inst = builder.AddIAdd(GetUintId(), num_bindings_id, param_ids[1]);
+  const uint32_t state_offset_id = inst->result_id();
+
+  inst =
+      builder.AddAccessChain(uint_ptr, desc_set_ptr_id,
+                             {{builder.GetUintConstantId(1), state_offset_id}});
+  const uint32_t state_start_ac_id = inst->result_id();
+
+  inst = builder.AddLoad(GetUintId(), state_start_ac_id, sizeof(uint32_t));
+  const uint32_t state_start_id = inst->result_id();
+
+  inst = builder.AddIAdd(GetUintId(), state_start_id, param_ids[2]);
+  const uint32_t state_entry_id = inst->result_id();
+
+  // Note: length starts from the beginning of the buffer, not the beginning of
+  // the data array
+  inst =
+      builder.AddAccessChain(uint_ptr, desc_set_ptr_id,
+                             {{builder.GetUintConstantId(1), state_entry_id}});
+  const uint32_t init_ac_id = inst->result_id();
+
+  inst = builder.AddLoad(GetUintId(), init_ac_id, sizeof(uint32_t));
+  const uint32_t init_status_id = inst->result_id();
+
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, init_status_id);
+
+  func->AddBasicBlock(std::move(new_blk_ptr));
+  func->SetFunctionEnd(EndFunction());
+
+  context()->AddFunction(std::move(func));
+  context()->AddDebug2Inst(NewGlobalName(func_id, "read_desc_init"));
+
+  read_init_func_id_ = func_id;
+  // Make sure function doesn't get processed by
+  // InstrumentPass::InstProcessCallTreeFromRoots()
+  param2output_func_id_[3] = func_id;
+  return read_init_func_id_;
 }
 
+// clang-format off
+// GLSL:
+// result = inst_bindless_read_desc_init(desc_set_id, binding_id, desc_idx_id);
+//
+// clang-format on
 uint32_t InstBindlessCheckPass::GenDebugReadInit(uint32_t var_id,
                                                  uint32_t desc_idx_id,
                                                  InstructionBuilder* builder) {
-  uint32_t binding_idx_id = builder->GetUintConstantId(var2binding_[var_id]);
-  uint32_t u_desc_idx_id = GenUintCastCode(desc_idx_id, builder);
-  // If desc index checking is not enabled, we know the offset of initialization
-  // entries is 1, so we can avoid loading this value and just add 1 to the
-  // descriptor set.
-  if (!desc_idx_enabled_) {
-    uint32_t desc_set_idx_id =
-        builder->GetUintConstantId(var2desc_set_[var_id] + 1);
-    return GenDebugDirectRead({desc_set_idx_id, binding_idx_id, u_desc_idx_id},
-                              builder);
-  } else {
-    uint32_t desc_set_base_id =
-        builder->GetUintConstantId(kDebugInputBindlessInitOffset);
-    uint32_t desc_set_idx_id =
-        builder->GetUintConstantId(var2desc_set_[var_id]);
-    return GenDebugDirectRead(
-        {desc_set_base_id, desc_set_idx_id, binding_idx_id, u_desc_idx_id},
-        builder);
-  }
+  const uint32_t func_id = GenDebugReadInitFunctionId();
+  const std::vector<uint32_t> args = {
+      builder->GetUintConstantId(var2desc_set_[var_id]),
+      builder->GetUintConstantId(var2binding_[var_id]),
+      GenUintCastCode(desc_idx_id, builder)};
+  return GenReadFunctionCall(func_id, args, builder);
 }
 
 uint32_t InstBindlessCheckPass::CloneOriginalImage(
@@ -248,9 +734,18 @@ bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
             ptr_inst->GetSingleWordInOperand(kSpvAccessChainIndex0IdInIdx);
         break;
       default:
-        ref->desc_idx_id = 0;
         break;
     }
+    auto decos =
+        context()->get_decoration_mgr()->GetDecorationsFor(ref->var_id, false);
+    for (const auto& deco : decos) {
+      spv::Decoration d = spv::Decoration(deco->GetSingleWordInOperand(1u));
+      if (d == spv::Decoration::DescriptorSet) {
+        ref->set = deco->GetSingleWordInOperand(2u);
+      } else if (d == spv::Decoration::Binding) {
+        ref->binding = deco->GetSingleWordInOperand(2u);
+      }
+    }
     return true;
   }
   // Reference is not load or store. If not an image-based reference, return.
@@ -300,6 +795,16 @@ bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
     // TODO(greg-lunarg): Handle additional possibilities?
     return false;
   }
+  auto decos =
+      context()->get_decoration_mgr()->GetDecorationsFor(ref->var_id, false);
+  for (const auto& deco : decos) {
+    spv::Decoration d = spv::Decoration(deco->GetSingleWordInOperand(1u));
+    if (d == spv::Decoration::DescriptorSet) {
+      ref->set = deco->GetSingleWordInOperand(2u);
+    } else if (d == spv::Decoration::Binding) {
+      ref->binding = deco->GetSingleWordInOperand(2u);
+    }
+  }
   return true;
 }
 
@@ -542,27 +1047,29 @@ void InstBindlessCheckPass::GenCheckCode(
   // Gen invalid block
   new_blk_ptr.reset(new BasicBlock(std::move(invalid_label)));
   builder.SetInsertPoint(&*new_blk_ptr);
-  uint32_t u_index_id = GenUintCastCode(ref->desc_idx_id, &builder);
+  const uint32_t u_set_id = builder.GetUintConstantId(ref->set);
+  const uint32_t u_binding_id = builder.GetUintConstantId(ref->binding);
+  const uint32_t u_index_id = GenUintCastCode(ref->desc_idx_id, &builder);
+  const uint32_t u_length_id = GenUintCastCode(length_id, &builder);
   if (offset_id != 0) {
+    const uint32_t u_offset_id = GenUintCastCode(offset_id, &builder);
     // 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,
-                        {error_id, u_index_id, u_offset_id, u_length_id},
+                        {error_id, u_set_id, u_binding_id, u_index_id,
+                         u_offset_id, u_length_id},
                         &builder);
   } else if (buffer_bounds_enabled_ || texel_buffer_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(
-        uid2offset_[ref->ref_inst->unique_id()], stage_idx,
-        {error_id, u_index_id, u_length_id, builder.GetUintConstantId(0)},
-        &builder);
+    GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
+                        {error_id, u_set_id, u_binding_id, u_index_id,
+                         u_length_id, builder.GetUintConstantId(0)},
+                        &builder);
   } else {
     // Uninitialized Descriptor - Normal error return
-    uint32_t u_length_id = GenUintCastCode(length_id, &builder);
-    GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
-                        {error_id, u_index_id, u_length_id}, &builder);
+    GenDebugStreamWrite(
+        uid2offset_[ref->ref_inst->unique_id()], stage_idx,
+        {error_id, u_set_id, u_binding_id, u_index_id, u_length_id}, &builder);
   }
   // Generate a ConstantNull, converting to uint64 if the type cannot be a null.
   if (new_ref_id != 0) {

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

@@ -110,10 +110,14 @@ class InstBindlessCheckPass : public InstrumentPass {
       UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
       std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
 
+  void SetupInputBufferIds();
+  uint32_t GenDebugReadLengthFunctionId();
+
   // Generate instructions into |builder| to read length of runtime descriptor
   // array |var_id| from debug input buffer and return id of value.
   uint32_t GenDebugReadLength(uint32_t var_id, InstructionBuilder* builder);
 
+  uint32_t GenDebugReadInitFunctionId();
   // Generate instructions into |builder| to read initialization status of
   // descriptor array |image_id| at |index_id| from debug input buffer and
   // return id of value.
@@ -124,14 +128,16 @@ class InstBindlessCheckPass : public InstrumentPass {
   // AnalyzeDescriptorReference. It is necessary and sufficient for further
   // analysis and regeneration of the reference.
   typedef struct RefAnalysis {
-    uint32_t desc_load_id;
-    uint32_t image_id;
-    uint32_t load_id;
-    uint32_t ptr_id;
-    uint32_t var_id;
-    uint32_t desc_idx_id;
-    uint32_t strg_class;
-    Instruction* ref_inst;
+    uint32_t desc_load_id{0};
+    uint32_t image_id{0};
+    uint32_t load_id{0};
+    uint32_t ptr_id{0};
+    uint32_t var_id{0};
+    uint32_t set{0};
+    uint32_t binding{0};
+    uint32_t desc_idx_id{0};
+    uint32_t strg_class{0};
+    Instruction* ref_inst{nullptr};
   } RefAnalysis;
 
   // Return size of type |ty_id| in bytes. Use |matrix_stride| and |col_major|
@@ -201,6 +207,13 @@ class InstBindlessCheckPass : public InstrumentPass {
 
   // Mapping from variable to binding
   std::unordered_map<uint32_t, uint32_t> var2binding_;
+
+  uint32_t read_length_func_id_{0};
+  uint32_t read_init_func_id_{0};
+  uint32_t desc_set_type_id_{0};
+  uint32_t desc_set_ptr_id_{0};
+  uint32_t input_buffer_struct_id_{0};
+  uint32_t input_buffer_ptr_id_{0};
 };
 
 }  // namespace opt

+ 18 - 0
3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.cpp

@@ -19,6 +19,24 @@
 namespace spvtools {
 namespace opt {
 
+bool InstBuffAddrCheckPass::InstrumentFunction(Function* func,
+                                               uint32_t stage_idx,
+                                               InstProcessFunction& pfn) {
+  // The bindless instrumentation pass adds functions that use
+  // BufferDeviceAddress They should not be instrumented by this pass.
+  Instruction* func_name_inst =
+      context()->GetNames(func->DefInst().result_id()).begin()->second;
+  if (func_name_inst) {
+    static const std::string kPrefix{"inst_bindless_"};
+    std::string func_name = func_name_inst->GetOperand(1).AsString();
+    if (func_name.size() >= kPrefix.size() &&
+        func_name.compare(0, kPrefix.size(), kPrefix) == 0) {
+      return false;
+    }
+  }
+  return InstrumentPass::InstrumentFunction(func, stage_idx, pfn);
+}
+
 uint32_t InstBuffAddrCheckPass::CloneOriginalReference(
     Instruction* ref_inst, InstructionBuilder* builder) {
   // Clone original ref with new result id (if load)

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

@@ -41,6 +41,9 @@ class InstBuffAddrCheckPass : public InstrumentPass {
 
   const char* name() const override { return "inst-buff-addr-check-pass"; }
 
+  bool InstrumentFunction(Function* func, uint32_t stage_idx,
+                          InstProcessFunction& pfn) override;
+
  private:
   // Return byte alignment of type |type_id|. Must be int, float, vector,
   // matrix, struct, array or physical pointer. Uses std430 alignment.

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

@@ -564,6 +564,19 @@ analysis::RuntimeArray* InstrumentPass::GetRuntimeArray(
   return type->AsRuntimeArray();
 }
 
+analysis::Array* InstrumentPass::GetArray(const analysis::Type* element,
+                                          uint32_t length) {
+  uint32_t length_id = context()->get_constant_mgr()->GetUIntConstId(length);
+  analysis::Array::LengthInfo length_info{
+      length_id, {analysis::Array::LengthInfo::Case::kConstant, length}};
+
+  analysis::Array r(element, length_info);
+
+  analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&r);
+  assert(type && type->AsArray());
+  return type->AsArray();
+}
+
 analysis::Function* InstrumentPass::GetFunction(
     const analysis::Type* return_val,
     const std::vector<const analysis::Type*>& args) {

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

@@ -270,6 +270,7 @@ class InstrumentPass : public Pass {
   analysis::Integer* GetInteger(uint32_t width, bool is_signed);
   analysis::Struct* GetStruct(const std::vector<const analysis::Type*>& fields);
   analysis::RuntimeArray* GetRuntimeArray(const analysis::Type* element);
+  analysis::Array* GetArray(const analysis::Type* element, uint32_t size);
   analysis::Function* GetFunction(
       const analysis::Type* return_val,
       const std::vector<const analysis::Type*>& args);
@@ -339,8 +340,8 @@ class InstrumentPass : public Pass {
   // If code is generated for an instruction, replace the instruction's
   // block with the new blocks that are generated. Continue processing at the
   // top of the last new block.
-  bool InstrumentFunction(Function* func, uint32_t stage_idx,
-                          InstProcessFunction& pfn);
+  virtual bool InstrumentFunction(Function* func, uint32_t stage_idx,
+                                  InstProcessFunction& pfn);
 
   // Call |pfn| on all functions in the call tree of the function
   // ids in |roots|.

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

@@ -480,9 +480,16 @@ class InstructionBuilder {
     return AddInstruction(std::move(new_inst));
   }
 
-  Instruction* AddLoad(uint32_t type_id, uint32_t base_ptr_id) {
+  Instruction* AddLoad(uint32_t type_id, uint32_t base_ptr_id,
+                       uint32_t alignment = 0) {
     std::vector<Operand> operands;
     operands.push_back({SPV_OPERAND_TYPE_ID, {base_ptr_id}});
+    if (alignment != 0) {
+      operands.push_back(
+          {SPV_OPERAND_TYPE_MEMORY_ACCESS,
+           {static_cast<uint32_t>(spv::MemoryAccessMask::Aligned)}});
+      operands.push_back({SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, {alignment}});
+    }
 
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> new_inst(

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

@@ -84,7 +84,7 @@ Pass::Status LICMPass::AnalyseAndHoistFromBB(
   bool modified = false;
   std::function<bool(Instruction*)> hoist_inst =
       [this, &loop, &modified](Instruction* inst) {
-        if (loop->ShouldHoistInstruction(this->context(), inst)) {
+        if (loop->ShouldHoistInstruction(*inst)) {
           if (!HoistInstruction(loop, inst)) {
             return false;
           }

+ 9 - 14
3rdparty/spirv-tools/source/opt/loop_descriptor.cpp

@@ -450,25 +450,20 @@ bool Loop::IsLCSSA() const {
   return true;
 }
 
-bool Loop::ShouldHoistInstruction(IRContext* context, Instruction* inst) {
-  return AreAllOperandsOutsideLoop(context, inst) &&
-         inst->IsOpcodeCodeMotionSafe();
+bool Loop::ShouldHoistInstruction(const Instruction& inst) const {
+  return inst.IsOpcodeCodeMotionSafe() && AreAllOperandsOutsideLoop(inst) &&
+         (!inst.IsLoad() || inst.IsReadOnlyLoad());
 }
 
-bool Loop::AreAllOperandsOutsideLoop(IRContext* context, Instruction* inst) {
-  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
-  bool all_outside_loop = true;
+bool Loop::AreAllOperandsOutsideLoop(const Instruction& inst) const {
+  analysis::DefUseManager* def_use_mgr = GetContext()->get_def_use_mgr();
 
-  const std::function<void(uint32_t*)> operand_outside_loop =
-      [this, &def_use_mgr, &all_outside_loop](uint32_t* id) {
-        if (this->IsInsideLoop(def_use_mgr->GetDef(*id))) {
-          all_outside_loop = false;
-          return;
-        }
+  const std::function<bool(const uint32_t*)> operand_outside_loop =
+      [this, &def_use_mgr](const uint32_t* id) {
+        return !this->IsInsideLoop(def_use_mgr->GetDef(*id));
       };
 
-  inst->ForEachInId(operand_outside_loop);
-  return all_outside_loop;
+  return inst.WhileEachInId(operand_outside_loop);
 }
 
 void Loop::ComputeLoopStructuredOrder(

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

@@ -296,12 +296,12 @@ class Loop {
   // as a nested child loop.
   inline void SetParent(Loop* parent) { parent_ = parent; }
 
-  // Returns true is the instruction is invariant and safe to move wrt loop
-  bool ShouldHoistInstruction(IRContext* context, Instruction* inst);
+  // Returns true is the instruction is invariant and safe to move wrt loop.
+  bool ShouldHoistInstruction(const Instruction& inst) const;
 
   // Returns true if all operands of inst are in basic blocks not contained in
-  // loop
-  bool AreAllOperandsOutsideLoop(IRContext* context, Instruction* inst);
+  // loop.
+  bool AreAllOperandsOutsideLoop(const Instruction& inst) const;
 
   // Extract the initial value from the |induction| variable and store it in
   // |value|. If the function couldn't find the initial value of |induction|

+ 11 - 5
3rdparty/spirv-tools/source/util/small_vector.h

@@ -15,7 +15,9 @@
 #ifndef SOURCE_UTIL_SMALL_VECTOR_H_
 #define SOURCE_UTIL_SMALL_VECTOR_H_
 
+#include <array>
 #include <cassert>
+#include <cstddef>
 #include <iostream>
 #include <memory>
 #include <utility>
@@ -461,14 +463,18 @@ class SmallVector {
   // The number of elements in |small_data_| that have been constructed.
   size_t size_;
 
-  // The pointed used to access the array of elements when the number of
-  // elements is small.
-  T* small_data_;
+  // A type with the same alignment and size as T, but will is POD.
+  struct alignas(T) PodType {
+    std::array<int8_t, sizeof(T)> data;
+  };
 
   // The actual data used to store the array elements.  It must never be used
   // directly, but must only be accessed through |small_data_|.
-  typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type
-      buffer[small_size];
+  PodType buffer[small_size];
+
+  // The pointed used to access the array of elements when the number of
+  // elements is small.
+  T* small_data_;
 
   // A pointer to a vector that is used to store the elements of the vector when
   // this size exceeds |small_size|.  If |large_data_| is nullptr, then the data

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

@@ -193,7 +193,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
     switch (dec) {
       case spv::Decoration::Location:
       case spv::Decoration::Component:
-        // Location is used for input, output and ray tracing stages.
+        // Location is used for input, output, tile image, and ray tracing
+        // stages.
         if (sc != spv::StorageClass::Input && sc != spv::StorageClass::Output &&
             sc != spv::StorageClass::RayPayloadKHR &&
             sc != spv::StorageClass::IncomingRayPayloadKHR &&
@@ -201,7 +202,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
             sc != spv::StorageClass::CallableDataKHR &&
             sc != spv::StorageClass::IncomingCallableDataKHR &&
             sc != spv::StorageClass::ShaderRecordBufferKHR &&
-            sc != spv::StorageClass::HitObjectAttributeNV) {
+            sc != spv::StorageClass::HitObjectAttributeNV &&
+            sc != spv::StorageClass::TileImageEXT) {
           return _.diag(SPV_ERROR_INVALID_ID, target)
                  << _.VkErrorID(6672) << _.SpvDecorationString(dec)
                  << " decoration must not be applied to this storage class";

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

@@ -76,7 +76,7 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _,
         }
         const auto constituent_result_type = _.FindDef(constituent->type_id());
         if (!constituent_result_type ||
-            component_type->opcode() != constituent_result_type->opcode()) {
+            component_type->id() != constituent_result_type->id()) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << opcode_name << " Constituent <id> "
                  << _.getIdName(constituent_id)

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

@@ -14,6 +14,7 @@
 
 #include <algorithm>
 
+#include "source/enum_string_mapping.h"
 #include "source/opcode.h"
 #include "source/val/instruction.h"
 #include "source/val/validate.h"

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

@@ -210,6 +210,7 @@ uint32_t GetPlaneCoordSize(const ImageTypeInfo& info) {
     case spv::Dim::Dim2D:
     case spv::Dim::Rect:
     case spv::Dim::SubpassData:
+    case spv::Dim::TileImageDataEXT:
       plane_size = 2;
       break;
     case spv::Dim::Dim3D:
@@ -218,6 +219,7 @@ uint32_t GetPlaneCoordSize(const ImageTypeInfo& info) {
       plane_size = 3;
       break;
     case spv::Dim::Max:
+    default:
       assert(0);
       break;
   }
@@ -853,6 +855,28 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Dim SubpassData requires format Unknown";
     }
+  } else if (info.dim == spv::Dim::TileImageDataEXT) {
+    if (_.IsVoidType(info.sampled_type)) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Dim TileImageDataEXT requires Sampled Type to be not "
+                "OpTypeVoid";
+    }
+    if (info.sampled != 2) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Dim TileImageDataEXT requires Sampled to be 2";
+    }
+    if (info.format != spv::ImageFormat::Unknown) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Dim TileImageDataEXT requires format Unknown";
+    }
+    if (info.depth != 0) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Dim TileImageDataEXT requires Depth to be 0";
+    }
+    if (info.arrayed != 0) {
+      return _.diag(SPV_ERROR_INVALID_DATA, inst)
+             << "Dim TileImageDataEXT requires Arrayed to be 0";
+    }
   } else {
     if (info.multisampled && (info.sampled == 2) &&
         !_.HasCapability(spv::Capability::StorageImageMultisample)) {
@@ -918,6 +942,8 @@ spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
   }
   // OpenCL requires Sampled=0, checked elsewhere.
   // Vulkan uses the Sampled=1 case.
+  // If Dim is TileImageDataEXT, Sampled must be 2 and this is validated
+  // elsewhere.
   if ((info.sampled != 0) && (info.sampled != 1)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << _.VkErrorID(4657)
@@ -1117,6 +1143,12 @@ spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
            << "Image Dim SubpassData cannot be used with OpImageTexelPointer";
   }
 
+  if (info.dim == spv::Dim::TileImageDataEXT) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Image Dim TileImageDataEXT cannot be used with "
+              "OpImageTexelPointer";
+  }
+
   const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
   if (!coord_type || !_.IsIntScalarOrVectorType(coord_type)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1623,6 +1655,12 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
                 spvOpcodeString(opcode));
   }
 
+  if (info.dim == spv::Dim::TileImageDataEXT) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Image Dim TileImageDataEXT cannot be used with "
+           << spvOpcodeString(opcode);
+  }
+
   if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t result_component_type =
         _.GetComponentType(actual_result_type);
@@ -1685,6 +1723,11 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
            << "Image 'Dim' cannot be SubpassData";
   }
 
+  if (info.dim == spv::Dim::TileImageDataEXT) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Image 'Dim' cannot be TileImageDataEXT";
+  }
+
   if (spv_result_t result = ValidateImageReadWrite(_, inst, info))
     return result;
 
@@ -1899,10 +1942,22 @@ spv_result_t ValidateImageQueryFormatOrOrder(ValidationState_t& _,
            << "Expected Result Type to be int scalar type";
   }
 
-  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 2)) != spv::Op::OpTypeImage) {
+  const uint32_t image_type = _.GetOperandTypeId(inst, 2);
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected operand to be of type OpTypeImage";
   }
+
+  ImageTypeInfo info;
+  if (!GetImageTypeInfo(_, image_type, &info)) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Corrupt image type definition";
+  }
+
+  if (info.dim == spv::Dim::TileImageDataEXT) {
+    return _.diag(SPV_ERROR_INVALID_DATA, inst)
+           << "Image 'Dim' cannot be TileImageDataEXT";
+  }
   return SPV_SUCCESS;
 }
 

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

@@ -502,6 +502,9 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _,
     case spv::ExecutionMode::DepthGreater:
     case spv::ExecutionMode::DepthLess:
     case spv::ExecutionMode::DepthUnchanged:
+    case spv::ExecutionMode::NonCoherentColorAttachmentReadEXT:
+    case spv::ExecutionMode::NonCoherentDepthAttachmentReadEXT:
+    case spv::ExecutionMode::NonCoherentStencilAttachmentReadEXT:
     case spv::ExecutionMode::PixelInterlockOrderedEXT:
     case spv::ExecutionMode::PixelInterlockUnorderedEXT:
     case spv::ExecutionMode::SampleInterlockOrderedEXT:

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

@@ -1572,6 +1572,7 @@ bool ValidationState_t::IsValidStorageClass(
       case spv::StorageClass::ShaderRecordBufferKHR:
       case spv::StorageClass::TaskPayloadWorkgroupEXT:
       case spv::StorageClass::HitObjectAttributeNV:
+      case spv::StorageClass::TileImageEXT:
         return true;
       default:
         return false;

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