Browse Source

Updated spirv-tools.

Бранимир Караџић 11 months ago
parent
commit
b0ef2b8c4b
51 changed files with 1452 additions and 136 deletions
  1. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  2. 23 0
      3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
  3. 4 0
      3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
  4. 2 0
      3rdparty/spirv-tools/include/generated/extension_enum.inc
  5. 2 1
      3rdparty/spirv-tools/include/generated/generators.inc
  6. 33 0
      3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
  7. 8 0
      3rdparty/spirv-tools/include/spirv-tools/libspirv.h
  8. 4 1
      3rdparty/spirv-tools/source/binary.cpp
  9. 2 0
      3rdparty/spirv-tools/source/disassemble.cpp
  10. 4 4
      3rdparty/spirv-tools/source/disassemble.h
  11. 3 0
      3rdparty/spirv-tools/source/enum_set.h
  12. 1 0
      3rdparty/spirv-tools/source/ext_inst.cpp
  13. 4 0
      3rdparty/spirv-tools/source/opcode.cpp
  14. 19 0
      3rdparty/spirv-tools/source/operand.cpp
  15. 9 1
      3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp
  16. 15 0
      3rdparty/spirv-tools/source/opt/eliminate_dead_members_pass.cpp
  17. 1 0
      3rdparty/spirv-tools/source/opt/folding_rules.cpp
  18. 27 1
      3rdparty/spirv-tools/source/opt/ir_context.cpp
  19. 2 1
      3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp
  20. 2 1
      3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp
  21. 2 1
      3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp
  22. 1 0
      3rdparty/spirv-tools/source/opt/loop_fission.cpp
  23. 1 0
      3rdparty/spirv-tools/source/opt/optimizer.cpp
  24. 25 1
      3rdparty/spirv-tools/source/opt/trim_capabilities_pass.cpp
  25. 1 0
      3rdparty/spirv-tools/source/opt/trim_capabilities_pass.h
  26. 48 0
      3rdparty/spirv-tools/source/opt/type_manager.cpp
  27. 53 1
      3rdparty/spirv-tools/source/opt/types.cpp
  28. 53 0
      3rdparty/spirv-tools/source/opt/types.h
  29. 7 26
      3rdparty/spirv-tools/source/print.cpp
  30. 105 29
      3rdparty/spirv-tools/source/spirv_target_env.cpp
  31. 7 0
      3rdparty/spirv-tools/source/spirv_target_env.h
  32. 1 0
      3rdparty/spirv-tools/source/table.cpp
  33. 4 2
      3rdparty/spirv-tools/source/text.cpp
  34. 2 1
      3rdparty/spirv-tools/source/val/function.h
  35. 1 0
      3rdparty/spirv-tools/source/val/validate.cpp
  36. 3 0
      3rdparty/spirv-tools/source/val/validate.h
  37. 125 3
      3rdparty/spirv-tools/source/val/validate_arithmetics.cpp
  38. 45 8
      3rdparty/spirv-tools/source/val/validate_conversion.cpp
  39. 1 1
      3rdparty/spirv-tools/source/val/validate_decorations.cpp
  40. 97 27
      3rdparty/spirv-tools/source/val/validate_extensions.cpp
  41. 83 2
      3rdparty/spirv-tools/source/val/validate_function.cpp
  42. 2 0
      3rdparty/spirv-tools/source/val/validate_id.cpp
  43. 1 0
      3rdparty/spirv-tools/source/val/validate_image.cpp
  44. 6 0
      3rdparty/spirv-tools/source/val/validate_instruction.cpp
  45. 2 2
      3rdparty/spirv-tools/source/val/validate_layout.cpp
  46. 236 9
      3rdparty/spirv-tools/source/val/validate_memory.cpp
  47. 2 3
      3rdparty/spirv-tools/source/val/validate_non_uniform.cpp
  48. 184 0
      3rdparty/spirv-tools/source/val/validate_tensor_layout.cpp
  49. 147 0
      3rdparty/spirv-tools/source/val/validate_type.cpp
  50. 15 5
      3rdparty/spirv-tools/source/val/validation_state.cpp
  51. 26 4
      3rdparty/spirv-tools/source/val/validation_state.h

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

@@ -1 +1 @@
-"v2024.4", "SPIRV-Tools v2024.4 v2024.4.rc1-27-g4a6ce351"
+"v2024.4", "SPIRV-Tools v2024.4 v2024.4.rc2-10-g7812970d"

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

@@ -24,8 +24,12 @@ static const spv::Capability pygen_variable_caps_AtomicFloat16MinMaxEXTAtomicFlo
 static const spv::Capability pygen_variable_caps_BFloat16ConversionINTEL[] = {spv::Capability::BFloat16ConversionINTEL};
 static const spv::Capability pygen_variable_caps_BindlessTextureNV[] = {spv::Capability::BindlessTextureNV};
 static const spv::Capability pygen_variable_caps_BlockingPipesINTEL[] = {spv::Capability::BlockingPipesINTEL};
+static const spv::Capability pygen_variable_caps_CooperativeMatrixConversionsNV[] = {spv::Capability::CooperativeMatrixConversionsNV};
 static const spv::Capability pygen_variable_caps_CooperativeMatrixKHR[] = {spv::Capability::CooperativeMatrixKHR};
 static const spv::Capability pygen_variable_caps_CooperativeMatrixNV[] = {spv::Capability::CooperativeMatrixNV};
+static const spv::Capability pygen_variable_caps_CooperativeMatrixPerElementOperationsNV[] = {spv::Capability::CooperativeMatrixPerElementOperationsNV};
+static const spv::Capability pygen_variable_caps_CooperativeMatrixReductionsNV[] = {spv::Capability::CooperativeMatrixReductionsNV};
+static const spv::Capability pygen_variable_caps_CooperativeMatrixTensorAddressingNV[] = {spv::Capability::CooperativeMatrixTensorAddressingNV};
 static const spv::Capability pygen_variable_caps_DemoteToHelperInvocation[] = {spv::Capability::DemoteToHelperInvocation};
 static const spv::Capability pygen_variable_caps_DerivativeControl[] = {spv::Capability::DerivativeControl};
 static const spv::Capability pygen_variable_caps_DeviceEnqueue[] = {spv::Capability::DeviceEnqueue};
@@ -94,6 +98,7 @@ static const spv::Capability pygen_variable_caps_SubgroupImageBlockIOINTEL[] = {
 static const spv::Capability pygen_variable_caps_SubgroupImageMediaBlockIOINTEL[] = {spv::Capability::SubgroupImageMediaBlockIOINTEL};
 static const spv::Capability pygen_variable_caps_SubgroupShuffleINTEL[] = {spv::Capability::SubgroupShuffleINTEL};
 static const spv::Capability pygen_variable_caps_SubgroupVoteKHR[] = {spv::Capability::SubgroupVoteKHR};
+static const spv::Capability pygen_variable_caps_TensorAddressingNV[] = {spv::Capability::TensorAddressingNV};
 static const spv::Capability pygen_variable_caps_TextureBlockMatch2QCOM[] = {spv::Capability::TextureBlockMatch2QCOM};
 static const spv::Capability pygen_variable_caps_TextureBlockMatchQCOM[] = {spv::Capability::TextureBlockMatchQCOM};
 static const spv::Capability pygen_variable_caps_TextureBoxFilterQCOM[] = {spv::Capability::TextureBoxFilterQCOM};
@@ -591,6 +596,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"ReorderThreadWithHintNV", spv::Op::OpReorderThreadWithHintNV, 0, nullptr, 1, pygen_variable_caps_ShaderInvocationReorderNV, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"TypeHitObjectNV", spv::Op::OpTypeHitObjectNV, 0, nullptr, 1, pygen_variable_caps_ShaderInvocationReorderNV, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"ImageSampleFootprintNV", spv::Op::OpImageSampleFootprintNV, 0, nullptr, 1, pygen_variable_caps_ImageFootprintNV, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_image_footprint, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixConvertNV", spv::Op::OpCooperativeMatrixConvertNV, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixConversionsNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"EmitMeshTasksEXT", spv::Op::OpEmitMeshTasksEXT, 0, nullptr, 1, pygen_variable_caps_MeshShadingEXT, 4, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"SetMeshOutputsEXT", spv::Op::OpSetMeshOutputsEXT, 0, nullptr, 1, pygen_variable_caps_MeshShadingEXT, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"GroupNonUniformPartitionNV", spv::Op::OpGroupNonUniformPartitionNV, 0, nullptr, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_subgroup_partitioned, 0xffffffffu, 0xffffffffu},
@@ -613,8 +619,25 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"CooperativeMatrixLengthNV", spv::Op::OpCooperativeMatrixLengthNV, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_cooperative_matrix, 0xffffffffu, 0xffffffffu},
   {"BeginInvocationInterlockEXT", spv::Op::OpBeginInvocationInterlockEXT, 0, nullptr, 3, pygen_variable_caps_FragmentShaderSampleInterlockEXTFragmentShaderPixelInterlockEXTFragmentShaderShadingRateInterlockEXT, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, 0xffffffffu, 0xffffffffu},
   {"EndInvocationInterlockEXT", spv::Op::OpEndInvocationInterlockEXT, 0, nullptr, 3, pygen_variable_caps_FragmentShaderSampleInterlockEXTFragmentShaderPixelInterlockEXTFragmentShaderShadingRateInterlockEXT, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixReduceNV", spv::Op::OpCooperativeMatrixReduceNV, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixReductionsNV, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixLoadTensorNV", spv::Op::OpCooperativeMatrixLoadTensorNV, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixTensorAddressingNV, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_MEMORY_ACCESS, SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixStoreTensorNV", spv::Op::OpCooperativeMatrixStoreTensorNV, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixTensorAddressingNV, 5, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_MEMORY_ACCESS, SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixPerElementOpNV", spv::Op::OpCooperativeMatrixPerElementOpNV, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixPerElementOperationsNV, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TypeTensorLayoutNV", spv::Op::OpTypeTensorLayoutNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 3, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TypeTensorViewNV", spv::Op::OpTypeTensorViewNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 4, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"CreateTensorLayoutNV", spv::Op::OpCreateTensorLayoutNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TensorLayoutSetDimensionNV", spv::Op::OpTensorLayoutSetDimensionNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TensorLayoutSetStrideNV", spv::Op::OpTensorLayoutSetStrideNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TensorLayoutSliceNV", spv::Op::OpTensorLayoutSliceNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TensorLayoutSetClampValueNV", spv::Op::OpTensorLayoutSetClampValueNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 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},
+  {"CreateTensorViewNV", spv::Op::OpCreateTensorViewNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TensorViewSetDimensionNV", spv::Op::OpTensorViewSetDimensionNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TensorViewSetStrideNV", spv::Op::OpTensorViewSetStrideNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"DemoteToHelperInvocation", spv::Op::OpDemoteToHelperInvocation, 1, pygen_variable_aliases_OpDemoteToHelperInvocationEXT, 1, pygen_variable_caps_DemoteToHelperInvocation, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
   {"IsHelperInvocationEXT", spv::Op::OpIsHelperInvocationEXT, 0, nullptr, 1, pygen_variable_caps_DemoteToHelperInvocation, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, 0xffffffffu, 0xffffffffu},
+  {"TensorViewSetClipNV", spv::Op::OpTensorViewSetClipNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"TensorLayoutSetBlockSizeNV", spv::Op::OpTensorLayoutSetBlockSizeNV, 0, nullptr, 1, pygen_variable_caps_TensorAddressingNV, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixTransposeNV", spv::Op::OpCooperativeMatrixTransposeNV, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixConversionsNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"ConvertUToImageNV", spv::Op::OpConvertUToImageNV, 0, nullptr, 1, pygen_variable_caps_BindlessTextureNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"ConvertUToSamplerNV", spv::Op::OpConvertUToSamplerNV, 0, nullptr, 1, pygen_variable_caps_BindlessTextureNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"ConvertImageToUNV", spv::Op::OpConvertImageToUNV, 0, nullptr, 1, pygen_variable_caps_BindlessTextureNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},

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


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

@@ -120,6 +120,7 @@ kSPV_NVX_multiview_per_view_attributes,
 kSPV_NV_bindless_texture,
 kSPV_NV_compute_shader_derivatives,
 kSPV_NV_cooperative_matrix,
+kSPV_NV_cooperative_matrix2,
 kSPV_NV_displacement_micromap,
 kSPV_NV_fragment_shader_barycentric,
 kSPV_NV_geometry_shader_passthrough,
@@ -135,6 +136,7 @@ kSPV_NV_shader_sm_builtins,
 kSPV_NV_shader_subgroup_partitioned,
 kSPV_NV_shading_rate,
 kSPV_NV_stereo_view_rendering,
+kSPV_NV_tensor_addressing,
 kSPV_NV_viewport_array2,
 kSPV_QCOM_image_processing,
 kSPV_QCOM_image_processing2,

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

@@ -43,4 +43,5 @@
 {42, "Rendong Liang", "spq", "Rendong Liang spq"},
 {43, "LLVM", "LLVM SPIR-V Backend", "LLVM LLVM SPIR-V Backend"},
 {44, "Robert Konrad", "Kongruent", "Robert Konrad Kongruent"},
-{45, "Kitsunebi Games", "Nuvk SPIR-V Emitter and DLSL compiler", "Kitsunebi Games Nuvk SPIR-V Emitter and DLSL compiler"},
+{45, "Kitsunebi Games", "Nuvk SPIR-V Emitter and DLSL compiler", "Kitsunebi Games Nuvk SPIR-V Emitter and DLSL compiler"},
+{46, "Nintendo", "", "Nintendo"},

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

@@ -100,6 +100,8 @@ static const spv::Capability pygen_variable_caps_CacheControlsINTEL[] = {spv::Ca
 static const spv::Capability pygen_variable_caps_ClipDistance[] = {spv::Capability::ClipDistance};
 static const spv::Capability pygen_variable_caps_ComputeDerivativeGroupLinearNVComputeDerivativeGroupLinearKHR[] = {spv::Capability::ComputeDerivativeGroupLinearNV, spv::Capability::ComputeDerivativeGroupLinearKHR};
 static const spv::Capability pygen_variable_caps_ComputeDerivativeGroupQuadsNVComputeDerivativeGroupQuadsKHR[] = {spv::Capability::ComputeDerivativeGroupQuadsNV, spv::Capability::ComputeDerivativeGroupQuadsKHR};
+static const spv::Capability pygen_variable_caps_CooperativeMatrixBlockLoadsNV[] = {spv::Capability::CooperativeMatrixBlockLoadsNV};
+static const spv::Capability pygen_variable_caps_CooperativeMatrixTensorAddressingNV[] = {spv::Capability::CooperativeMatrixTensorAddressingNV};
 static const spv::Capability pygen_variable_caps_CoreBuiltinsARM[] = {spv::Capability::CoreBuiltinsARM};
 static const spv::Capability pygen_variable_caps_CullDistance[] = {spv::Capability::CullDistance};
 static const spv::Capability pygen_variable_caps_DenormFlushToZero[] = {spv::Capability::DenormFlushToZero};
@@ -351,6 +353,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_NVX_multiview_per_view_
 static const spvtools::Extension pygen_variable_exts_SPV_NVX_multiview_per_view_attributesSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_NVX_multiview_per_view_attributes, spvtools::Extension::kSPV_NV_mesh_shader};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_bindless_texture[] = {spvtools::Extension::kSPV_NV_bindless_texture};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_cooperative_matrix[] = {spvtools::Extension::kSPV_NV_cooperative_matrix};
+static const spvtools::Extension pygen_variable_exts_SPV_NV_cooperative_matrix2[] = {spvtools::Extension::kSPV_NV_cooperative_matrix2};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_displacement_micromap[] = {spvtools::Extension::kSPV_NV_displacement_micromap};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_geometry_shader_passthrough[] = {spvtools::Extension::kSPV_NV_geometry_shader_passthrough};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_NV_mesh_shader};
@@ -365,6 +368,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_invocation_re
 static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_sm_builtins[] = {spvtools::Extension::kSPV_NV_shader_sm_builtins};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_subgroup_partitioned[] = {spvtools::Extension::kSPV_NV_shader_subgroup_partitioned};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_stereo_view_rendering[] = {spvtools::Extension::kSPV_NV_stereo_view_rendering};
+static const spvtools::Extension pygen_variable_exts_SPV_NV_tensor_addressing[] = {spvtools::Extension::kSPV_NV_tensor_addressing};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_viewport_array2[] = {spvtools::Extension::kSPV_NV_viewport_array2};
 static const spvtools::Extension pygen_variable_exts_SPV_QCOM_image_processing[] = {spvtools::Extension::kSPV_QCOM_image_processing};
 static const spvtools::Extension pygen_variable_exts_SPV_QCOM_image_processing2[] = {spvtools::Extension::kSPV_QCOM_image_processing2};
@@ -1317,6 +1321,12 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"AtomicFloat16VectorNV", 5404, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_shader_atomic_fp16_vector, {}, 0xffffffffu, 0xffffffffu},
   {"RayTracingDisplacementMicromapNV", 5409, 0, nullptr, 1, pygen_variable_caps_RayTracingKHR, 1, pygen_variable_exts_SPV_NV_displacement_micromap, {}, 0xffffffffu, 0xffffffffu},
   {"RawAccessChainsNV", 5414, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_raw_access_chains, {}, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixReductionsNV", 5430, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_cooperative_matrix2, {}, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixConversionsNV", 5431, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_cooperative_matrix2, {}, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixPerElementOperationsNV", 5432, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_cooperative_matrix2, {}, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixTensorAddressingNV", 5433, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_cooperative_matrix2, {}, 0xffffffffu, 0xffffffffu},
+  {"CooperativeMatrixBlockLoadsNV", 5434, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_cooperative_matrix2, {}, 0xffffffffu, 0xffffffffu},
+  {"TensorAddressingNV", 5439, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_NV_tensor_addressing, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupShuffleINTEL", 5568, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupBufferBlockIOINTEL", 5569, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
   {"SubgroupImageBlockIOINTEL", 5570, 0, nullptr, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
@@ -1434,6 +1444,26 @@ static const spv_operand_desc_t pygen_variable_CooperativeMatrixUseEntries[] = {
   {"MatrixAccumulatorKHR", 2, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
 };
 
+static const spv_operand_desc_t pygen_variable_CooperativeMatrixReduceEntries[] = {
+  {"Row", 0x0001, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"Column", 0x0002, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"2x2", 0x0004, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
+};
+
+static const spv_operand_desc_t pygen_variable_TensorClampModeEntries[] = {
+  {"Undefined", 0, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"Constant", 1, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"ClampToEdge", 2, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"Repeat", 3, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"RepeatMirrored", 4, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
+};
+
+static const spv_operand_desc_t pygen_variable_TensorAddressingOperandsEntries[] = {
+  {"None", 0x0000, 0, nullptr, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"TensorView", 0x0001, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixTensorAddressingNV, 0, nullptr, {SPV_OPERAND_TYPE_ID}, 0xffffffffu, 0xffffffffu},
+  {"DecodeFunc", 0x0002, 0, nullptr, 1, pygen_variable_caps_CooperativeMatrixBlockLoadsNV, 0, nullptr, {SPV_OPERAND_TYPE_ID}, 0xffffffffu, 0xffffffffu}
+};
+
 static const spv_operand_desc_t pygen_variable_InitializationModeQualifierEntries[] = {
   {"InitOnDeviceReprogramINTEL", 0, 0, nullptr, 1, pygen_variable_caps_GlobalVariableFPGADecorationsINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
   {"InitOnDeviceResetINTEL", 1, 0, nullptr, 1, pygen_variable_caps_GlobalVariableFPGADecorationsINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
@@ -1626,6 +1656,9 @@ static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = {
   {SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS, ARRAY_SIZE(pygen_variable_CooperativeMatrixOperandsEntries), pygen_variable_CooperativeMatrixOperandsEntries},
   {SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_LAYOUT, ARRAY_SIZE(pygen_variable_CooperativeMatrixLayoutEntries), pygen_variable_CooperativeMatrixLayoutEntries},
   {SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_USE, ARRAY_SIZE(pygen_variable_CooperativeMatrixUseEntries), pygen_variable_CooperativeMatrixUseEntries},
+  {SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE, ARRAY_SIZE(pygen_variable_CooperativeMatrixReduceEntries), pygen_variable_CooperativeMatrixReduceEntries},
+  {SPV_OPERAND_TYPE_TENSOR_CLAMP_MODE, ARRAY_SIZE(pygen_variable_TensorClampModeEntries), pygen_variable_TensorClampModeEntries},
+  {SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS, ARRAY_SIZE(pygen_variable_TensorAddressingOperandsEntries), pygen_variable_TensorAddressingOperandsEntries},
   {SPV_OPERAND_TYPE_INITIALIZATION_MODE_QUALIFIER, ARRAY_SIZE(pygen_variable_InitializationModeQualifierEntries), pygen_variable_InitializationModeQualifierEntries},
   {SPV_OPERAND_TYPE_LOAD_CACHE_CONTROL, ARRAY_SIZE(pygen_variable_LoadCacheControlEntries), pygen_variable_LoadCacheControlEntries},
   {SPV_OPERAND_TYPE_STORE_CACHE_CONTROL, ARRAY_SIZE(pygen_variable_StoreCacheControlEntries), pygen_variable_StoreCacheControlEntries},

+ 8 - 0
3rdparty/spirv-tools/include/spirv-tools/libspirv.h

@@ -315,6 +315,12 @@ typedef enum spv_operand_type_t {
   SPV_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS,
   // Optional enum type from SPV_NV_raw_access_chains
   SPV_OPERAND_TYPE_OPTIONAL_RAW_ACCESS_CHAIN_OPERANDS,
+  // Enum type from SPV_NV_tensor_addressing
+  SPV_OPERAND_TYPE_TENSOR_CLAMP_MODE,
+  // Enum type from SPV_NV_cooperative_matrix2
+  SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE,
+  // Enum type from SPV_NV_cooperative_matrix2
+  SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS,
 
   // This is a sentinel value, and does not represent an operand type.
   // It should come last.
@@ -535,6 +541,7 @@ SPIRV_TOOLS_EXPORT const char* spvSoftwareVersionDetailsString(void);
 //    SPV_ENV_VULKAN_1_1_SPIRV_1_4 ->  SPIR-V 1.4
 //    SPV_ENV_VULKAN_1_2           ->  SPIR-V 1.5
 //    SPV_ENV_VULKAN_1_3           ->  SPIR-V 1.6
+//    SPV_ENV_VULKAN_1_4           ->  SPIR-V 1.6
 // Consult the description of API entry points for specific rules.
 typedef enum {
   SPV_ENV_UNIVERSAL_1_0,  // SPIR-V 1.0 latest revision, no other restrictions.
@@ -572,6 +579,7 @@ typedef enum {
 
   SPV_ENV_UNIVERSAL_1_6,  // SPIR-V 1.6 latest revision, no other restrictions.
   SPV_ENV_VULKAN_1_3,     // Vulkan 1.3 latest revision.
+  SPV_ENV_VULKAN_1_4,     // Vulkan 1.4 latest revision.
 
   SPV_ENV_MAX  // Keep this as the last enum value.
 } spv_target_env;

+ 4 - 1
3rdparty/spirv-tools/source/binary.cpp

@@ -717,13 +717,16 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
     case SPV_OPERAND_TYPE_LOOP_CONTROL:
     case SPV_OPERAND_TYPE_IMAGE:
     case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
+    case SPV_OPERAND_TYPE_MEMORY_ACCESS:
     case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
     case SPV_OPERAND_TYPE_OPTIONAL_RAW_ACCESS_CHAIN_OPERANDS:
     case SPV_OPERAND_TYPE_SELECTION_CONTROL:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
     case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS:
-    case SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS: {
+    case SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS:
+    case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE:
+    case SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS: {
       // This operand is a mask.
 
       // Map an optional operand type to its corresponding concrete type.

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

@@ -23,8 +23,10 @@
 #include <cassert>
 #include <cstring>
 #include <iomanip>
+#include <ios>
 #include <memory>
 #include <set>
+#include <sstream>
 #include <stack>
 #include <unordered_map>
 #include <utility>

+ 4 - 4
3rdparty/spirv-tools/source/disassemble.h

@@ -15,7 +15,7 @@
 #ifndef SOURCE_DISASSEMBLE_H_
 #define SOURCE_DISASSEMBLE_H_
 
-#include <iosfwd>
+#include <ios>
 #include <sstream>
 #include <string>
 
@@ -94,11 +94,11 @@ class InstructionDisassembler {
   // Emits an operand for the given instruction, where the instruction
   // is at offset words from the start of the binary.
   void EmitOperand(std::ostream& stream, const spv_parsed_instruction_t& inst,
-                   const uint16_t operand_index) const;
+                   uint16_t operand_index) const;
 
   // Emits a mask expression for the given mask word of the specified type.
-  void EmitMaskOperand(std::ostream& stream, const spv_operand_type_t type,
-                       const uint32_t word) const;
+  void EmitMaskOperand(std::ostream& stream, spv_operand_type_t type,
+                       uint32_t word) const;
 
   // Generate part of the instruction as a comment to be added to
   // |id_comments_|.

+ 3 - 0
3rdparty/spirv-tools/source/enum_set.h

@@ -12,11 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <stddef.h>
+
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
 #include <functional>
 #include <initializer_list>
+#include <iterator>
 #include <limits>
 #include <type_traits>
 #include <vector>

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

@@ -102,6 +102,7 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       *pExtInstTable = &kTable_1_0;
       return SPV_SUCCESS;
     default:

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

@@ -382,6 +382,8 @@ int32_t spvOpcodeGeneratesType(spv::Op op) {
     case spv::Op::OpTypeRayQueryKHR:
     case spv::Op::OpTypeHitObjectNV:
     case spv::Op::OpTypeUntypedPointerKHR:
+    case spv::Op::OpTypeTensorLayoutNV:
+    case spv::Op::OpTypeTensorViewNV:
       return true;
     default:
       // In particular, OpTypeForwardPointer does not generate a type,
@@ -419,6 +421,7 @@ bool spvOpcodeIsLoad(const spv::Op opcode) {
     case spv::Op::OpImageSampleProjExplicitLod:
     case spv::Op::OpImageSampleProjDrefImplicitLod:
     case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSampleFootprintNV:
     case spv::Op::OpImageFetch:
     case spv::Op::OpImageGather:
     case spv::Op::OpImageDrefGather:
@@ -745,6 +748,7 @@ bool spvOpcodeIsImageSample(const spv::Op opcode) {
     case spv::Op::OpImageSparseSampleExplicitLod:
     case spv::Op::OpImageSparseSampleDrefImplicitLod:
     case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleFootprintNV:
       return true;
     default:
       return false;

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

@@ -231,6 +231,12 @@ const char* spvOperandTypeStr(spv_operand_type_t type) {
       return "cooperative matrix layout";
     case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_USE:
       return "cooperative matrix use";
+    case SPV_OPERAND_TYPE_TENSOR_CLAMP_MODE:
+      return "tensor clamp mode";
+    case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE:
+      return "cooperative matrix reduce";
+    case SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS:
+      return "tensor addressing operands";
     case SPV_OPERAND_TYPE_INITIALIZATION_MODE_QUALIFIER:
       return "initialization mode qualifier";
     case SPV_OPERAND_TYPE_HOST_ACCESS_QUALIFIER:
@@ -389,6 +395,7 @@ bool spvOperandIsConcrete(spv_operand_type_t type) {
     case SPV_OPERAND_TYPE_STORE_CACHE_CONTROL:
     case SPV_OPERAND_TYPE_NAMED_MAXIMUM_NUMBER_OF_REGISTERS:
     case SPV_OPERAND_TYPE_FPENCODING:
+    case SPV_OPERAND_TYPE_TENSOR_CLAMP_MODE:
       return true;
     default:
       break;
@@ -409,6 +416,8 @@ bool spvOperandIsConcreteMask(spv_operand_type_t type) {
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
     case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS:
     case SPV_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS:
+    case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE:
+    case SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS:
       return true;
     default:
       break;
@@ -598,6 +607,16 @@ std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
     case spv::Op::OpTypeArray:
       out = [](unsigned index) { return index == 1; };
       break;
+    case spv::Op::OpCooperativeMatrixPerElementOpNV:
+      out = [](unsigned index) { return index == 3; };
+      break;
+    case spv::Op::OpCooperativeMatrixReduceNV:
+      out = [](unsigned index) { return index == 4; };
+      break;
+    case spv::Op::OpCooperativeMatrixLoadTensorNV:
+      // approximate, due to variable operands
+      out = [](unsigned index) { return index > 6; };
+      break;
     default:
       out = [](unsigned) { return false; };
       break;

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

@@ -43,6 +43,7 @@ constexpr uint32_t kGlobalVariableVariableIndex = 12;
 constexpr uint32_t kExtInstSetInIdx = 0;
 constexpr uint32_t kExtInstOpInIdx = 1;
 constexpr uint32_t kInterpolantInIdx = 2;
+constexpr uint32_t kCooperativeMatrixLoadSourceAddrInIdx = 0;
 
 // Sorting functor to present annotation instructions in an easy-to-process
 // order. The functor orders by opcode first and falls back on unique id
@@ -438,6 +439,11 @@ uint32_t AggressiveDCEPass::GetLoadedVariableFromNonFunctionCalls(
       }
       break;
     }
+    case spv::Op::OpCooperativeMatrixLoadNV:
+    case spv::Op::OpCooperativeMatrixLoadKHR:
+    case spv::Op::OpCooperativeMatrixLoadTensorNV:
+      return GetVariableId(
+          inst->GetSingleWordInOperand(kCooperativeMatrixLoadSourceAddrInIdx));
     default:
       break;
   }
@@ -670,6 +676,7 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
     auto op = dbg.GetShader100DebugOpcode();
     if (op == NonSemanticShaderDebugInfo100DebugCompilationUnit ||
         op == NonSemanticShaderDebugInfo100DebugEntryPoint ||
+        op == NonSemanticShaderDebugInfo100DebugSource ||
         op == NonSemanticShaderDebugInfo100DebugSourceContinued) {
       AddToWorklist(&dbg);
     }
@@ -1029,7 +1036,8 @@ void AggressiveDCEPass::InitExtensions() {
       "SPV_KHR_compute_shader_derivatives",
       "SPV_NV_cooperative_matrix",
       "SPV_KHR_cooperative_matrix",
-      "SPV_KHR_ray_tracing_position_fetch"
+      "SPV_KHR_ray_tracing_position_fetch",
+      "SPV_KHR_fragment_shading_rate"
   });
   // clang-format on
 }

+ 15 - 0
3rdparty/spirv-tools/source/opt/eliminate_dead_members_pass.cpp

@@ -70,6 +70,11 @@ void EliminateDeadMembersPass::FindLiveMembers() {
             MarkPointeeTypeAsFullUsed(inst.type_id());
           break;
       }
+    } else if (inst.opcode() == spv::Op::OpTypePointer) {
+      uint32_t storage_class = inst.GetSingleWordInOperand(0);
+      if (storage_class == uint32_t(spv::StorageClass::PhysicalStorageBuffer)) {
+        MarkTypeAsFullyUsed(inst.GetSingleWordInOperand(1));
+      }
     }
   }
 
@@ -200,6 +205,8 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForExtract(
       case spv::Op::OpTypeRuntimeArray:
       case spv::Op::OpTypeVector:
       case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeCooperativeMatrixNV:
+      case spv::Op::OpTypeCooperativeMatrixKHR:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -246,6 +253,8 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForAccessChain(
       case spv::Op::OpTypeRuntimeArray:
       case spv::Op::OpTypeVector:
       case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeCooperativeMatrixNV:
+      case spv::Op::OpTypeCooperativeMatrixKHR:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -505,6 +514,8 @@ bool EliminateDeadMembersPass::UpdateAccessChain(Instruction* inst) {
       case spv::Op::OpTypeRuntimeArray:
       case spv::Op::OpTypeVector:
       case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeCooperativeMatrixNV:
+      case spv::Op::OpTypeCooperativeMatrixKHR:
         new_operands.emplace_back(inst->GetInOperand(i));
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
@@ -578,6 +589,8 @@ bool EliminateDeadMembersPass::UpdateCompsiteExtract(Instruction* inst) {
       case spv::Op::OpTypeRuntimeArray:
       case spv::Op::OpTypeVector:
       case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeCooperativeMatrixNV:
+      case spv::Op::OpTypeCooperativeMatrixKHR:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -639,6 +652,8 @@ bool EliminateDeadMembersPass::UpdateCompositeInsert(Instruction* inst) {
       case spv::Op::OpTypeRuntimeArray:
       case spv::Op::OpTypeVector:
       case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeCooperativeMatrixNV:
+      case spv::Op::OpTypeCooperativeMatrixKHR:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:

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

@@ -1790,6 +1790,7 @@ bool CompositeExtractFeedingConstruct(
       return false;
     }
   }
+  assert(first_element_inst != nullptr);
 
   // The last check it to see that the object being extracted from is the
   // correct type.

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

@@ -926,9 +926,35 @@ uint32_t IRContext::GetBuiltinInputVarId(uint32_t builtin) {
 
 void IRContext::AddCalls(const Function* func, std::queue<uint32_t>* todo) {
   for (auto bi = func->begin(); bi != func->end(); ++bi)
-    for (auto ii = bi->begin(); ii != bi->end(); ++ii)
+    for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
       if (ii->opcode() == spv::Op::OpFunctionCall)
         todo->push(ii->GetSingleWordInOperand(0));
+      if (ii->opcode() == spv::Op::OpCooperativeMatrixPerElementOpNV)
+        todo->push(ii->GetSingleWordInOperand(1));
+      if (ii->opcode() == spv::Op::OpCooperativeMatrixReduceNV)
+        todo->push(ii->GetSingleWordInOperand(2));
+      if (ii->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV) {
+        const auto memory_operands_index = 3;
+        auto mask = ii->GetSingleWordInOperand(memory_operands_index);
+
+        uint32_t count = 1;
+        if (mask & uint32_t(spv::MemoryAccessMask::Aligned)) ++count;
+        if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR))
+          ++count;
+        if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR))
+          ++count;
+
+        const auto tensor_operands_index = memory_operands_index + count;
+        mask = ii->GetSingleWordInOperand(tensor_operands_index);
+        count = 1;
+        if (mask & uint32_t(spv::TensorAddressingOperandsMask::TensorView))
+          ++count;
+
+        if (mask & uint32_t(spv::TensorAddressingOperandsMask::DecodeFunc)) {
+          todo->push(ii->GetSingleWordInOperand(tensor_operands_index + count));
+        }
+      }
+    }
 }
 
 bool IRContext::ProcessEntryPointCallTree(ProcessFunction& pfn) {

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

@@ -430,7 +430,8 @@ void LocalAccessChainConvertPass::InitExtensions() {
        "SPV_NV_bindless_texture", "SPV_EXT_shader_atomic_float_add",
        "SPV_EXT_fragment_shader_interlock",
        "SPV_KHR_compute_shader_derivatives", "SPV_NV_cooperative_matrix",
-       "SPV_KHR_cooperative_matrix", "SPV_KHR_ray_tracing_position_fetch"});
+       "SPV_KHR_cooperative_matrix", "SPV_KHR_ray_tracing_position_fetch",
+       "SPV_KHR_fragment_shading_rate"});
 }
 
 bool LocalAccessChainConvertPass::AnyIndexIsOutOfBounds(

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

@@ -294,7 +294,8 @@ void LocalSingleBlockLoadStoreElimPass::InitExtensions() {
                                 "SPV_KHR_compute_shader_derivatives",
                                 "SPV_NV_cooperative_matrix",
                                 "SPV_KHR_cooperative_matrix",
-                                "SPV_KHR_ray_tracing_position_fetch"});
+                                "SPV_KHR_ray_tracing_position_fetch",
+                                "SPV_KHR_fragment_shading_rate"});
 }
 
 }  // namespace opt

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

@@ -144,7 +144,8 @@ void LocalSingleStoreElimPass::InitExtensionAllowList() {
                                 "SPV_KHR_compute_shader_derivatives",
                                 "SPV_NV_cooperative_matrix",
                                 "SPV_KHR_cooperative_matrix",
-                                "SPV_KHR_ray_tracing_position_fetch"});
+                                "SPV_KHR_ray_tracing_position_fetch",
+                                "SPV_KHR_fragment_shading_rate"});
 }
 bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) {
   std::vector<Instruction*> users;

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

@@ -499,6 +499,7 @@ Pass::Status LoopFissionPass::Process() {
       // next iteration.
       if (split_multiple_times_) {
         inner_most_loops = std::move(new_loops_to_split);
+        new_loops_to_split = {};
       } else {
         break;
       }

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

@@ -18,6 +18,7 @@
 #include <charconv>
 #include <memory>
 #include <string>
+#include <system_error>
 #include <unordered_map>
 #include <utility>
 #include <vector>

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

@@ -49,6 +49,7 @@ constexpr uint32_t kOpTypeImageMSIndex = kOpTypeImageArrayedIndex + 1;
 constexpr uint32_t kOpTypeImageSampledIndex = kOpTypeImageMSIndex + 1;
 constexpr uint32_t kOpTypeImageFormatIndex = kOpTypeImageSampledIndex + 1;
 constexpr uint32_t kOpImageReadImageIndex = 0;
+constexpr uint32_t kOpImageWriteImageIndex = 0;
 constexpr uint32_t kOpImageSparseReadImageIndex = 0;
 constexpr uint32_t kOpExtInstSetInIndex = 0;
 constexpr uint32_t kOpExtInstInstructionInIndex = 1;
@@ -338,6 +339,8 @@ Handler_OpImageRead_StorageImageReadWithoutFormat(
   const uint32_t dim = type->GetSingleWordInOperand(kOpTypeImageDimIndex);
   const uint32_t format = type->GetSingleWordInOperand(kOpTypeImageFormatIndex);
 
+  // If the Image Format is Unknown and Dim is SubpassData,
+  // StorageImageReadWithoutFormat is required.
   const bool is_unknown = spv::ImageFormat(format) == spv::ImageFormat::Unknown;
   const bool requires_capability_for_unknown =
       spv::Dim(dim) != spv::Dim::SubpassData;
@@ -346,6 +349,26 @@ Handler_OpImageRead_StorageImageReadWithoutFormat(
              : std::nullopt;
 }
 
+static std::optional<spv::Capability>
+Handler_OpImageWrite_StorageImageWriteWithoutFormat(
+    const Instruction* instruction) {
+  assert(instruction->opcode() == spv::Op::OpImageWrite &&
+         "This handler only support OpImageWrite opcodes.");
+  const auto* def_use_mgr = instruction->context()->get_def_use_mgr();
+
+  const uint32_t image_index =
+      instruction->GetSingleWordInOperand(kOpImageWriteImageIndex);
+  const uint32_t type_index = def_use_mgr->GetDef(image_index)->type_id();
+
+  // If the Image Format is Unknown, StorageImageWriteWithoutFormat is required.
+  const Instruction* type = def_use_mgr->GetDef(type_index);
+  const uint32_t format = type->GetSingleWordInOperand(kOpTypeImageFormatIndex);
+  const bool is_unknown = spv::ImageFormat(format) == spv::ImageFormat::Unknown;
+  return is_unknown
+             ? std::optional(spv::Capability::StorageImageWriteWithoutFormat)
+             : std::nullopt;
+}
+
 static std::optional<spv::Capability>
 Handler_OpImageSparseRead_StorageImageReadWithoutFormat(
     const Instruction* instruction) {
@@ -365,9 +388,10 @@ Handler_OpImageSparseRead_StorageImageReadWithoutFormat(
 }
 
 // Opcode of interest to determine capabilities requirements.
-constexpr std::array<std::pair<spv::Op, OpcodeHandler>, 12> kOpcodeHandlers{{
+constexpr std::array<std::pair<spv::Op, OpcodeHandler>, 13> kOpcodeHandlers{{
     // clang-format off
     {spv::Op::OpImageRead,         Handler_OpImageRead_StorageImageReadWithoutFormat},
+    {spv::Op::OpImageWrite,        Handler_OpImageWrite_StorageImageWriteWithoutFormat},
     {spv::Op::OpImageSparseRead,   Handler_OpImageSparseRead_StorageImageReadWithoutFormat},
     {spv::Op::OpTypeFloat,         Handler_OpTypeFloat_Float16 },
     {spv::Op::OpTypeFloat,         Handler_OpTypeFloat_Float64 },

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

@@ -100,6 +100,7 @@ class TrimCapabilitiesPass : public Pass {
       spv::Capability::Shader,
       spv::Capability::ShaderClockKHR,
       spv::Capability::StorageImageReadWithoutFormat,
+      spv::Capability::StorageImageWriteWithoutFormat,
       spv::Capability::StorageInputOutput16,
       spv::Capability::StoragePushConstant16,
       spv::Capability::StorageUniform16,

+ 48 - 0
3rdparty/spirv-tools/source/opt/type_manager.cpp

@@ -441,6 +441,28 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) {
               {SPV_OPERAND_TYPE_ID, {coop_mat->use_id()}}});
       break;
     }
+    case Type::kTensorLayoutNV: {
+      auto tensor_layout = type->AsTensorLayoutNV();
+      typeInst = MakeUnique<Instruction>(
+          context(), spv::Op::OpTypeTensorLayoutNV, 0, id,
+          std::initializer_list<Operand>{
+              {SPV_OPERAND_TYPE_ID, {tensor_layout->dim_id()}},
+              {SPV_OPERAND_TYPE_ID, {tensor_layout->clamp_mode_id()}}});
+      break;
+    }
+    case Type::kTensorViewNV: {
+      auto tensor_view = type->AsTensorViewNV();
+      std::vector<Operand> operands;
+      operands.push_back(Operand{SPV_OPERAND_TYPE_ID, {tensor_view->dim_id()}});
+      operands.push_back(
+          Operand{SPV_OPERAND_TYPE_ID, {tensor_view->has_dimensions_id()}});
+      for (auto p : tensor_view->perm()) {
+        operands.push_back(Operand{SPV_OPERAND_TYPE_ID, {p}});
+      }
+      typeInst = MakeUnique<Instruction>(context(), spv::Op::OpTypeTensorViewNV,
+                                         0, id, operands);
+      break;
+    }
     default:
       assert(false && "Unexpected type");
       break;
@@ -667,6 +689,18 @@ Type* TypeManager::RebuildType(uint32_t type_id, const Type& type) {
           cm_type->use_id());
       break;
     }
+    case Type::kTensorLayoutNV: {
+      const TensorLayoutNV* tl_type = type.AsTensorLayoutNV();
+      rebuilt_ty = MakeUnique<TensorLayoutNV>(tl_type->dim_id(),
+                                              tl_type->clamp_mode_id());
+      break;
+    }
+    case Type::kTensorViewNV: {
+      const TensorViewNV* tv_type = type.AsTensorViewNV();
+      rebuilt_ty = MakeUnique<TensorViewNV>(
+          tv_type->dim_id(), tv_type->has_dimensions_id(), tv_type->perm());
+      break;
+    }
     default:
       assert(false && "Unhandled type");
       return nullptr;
@@ -914,6 +948,20 @@ Type* TypeManager::RecordIfTypeDefinition(const Instruction& inst) {
     case spv::Op::OpTypeHitObjectNV:
       type = new HitObjectNV();
       break;
+    case spv::Op::OpTypeTensorLayoutNV:
+      type = new TensorLayoutNV(inst.GetSingleWordInOperand(0),
+                                inst.GetSingleWordInOperand(1));
+      break;
+    case spv::Op::OpTypeTensorViewNV: {
+      const auto count = inst.NumOperands();
+      std::vector<uint32_t> perm;
+      for (uint32_t i = 2; i < count; ++i) {
+        perm.push_back(inst.GetSingleWordOperand(i));
+      }
+      type = new TensorViewNV(inst.GetSingleWordInOperand(0),
+                              inst.GetSingleWordInOperand(1), perm);
+      break;
+    }
     default:
       assert(false && "Type not handled by the type manager.");
       break;

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

@@ -179,6 +179,8 @@ bool Type::operator==(const Type& other) const {
     DeclareKindCase(CooperativeMatrixKHR);
     DeclareKindCase(RayQueryKHR);
     DeclareKindCase(HitObjectNV);
+    DeclareKindCase(TensorLayoutNV);
+    DeclareKindCase(TensorViewNV);
 #undef DeclareKindCase
     default:
       assert(false && "Unhandled type");
@@ -235,6 +237,8 @@ size_t Type::ComputeHashValue(size_t hash, SeenTypes* seen) const {
     DeclareKindCase(CooperativeMatrixKHR);
     DeclareKindCase(RayQueryKHR);
     DeclareKindCase(HitObjectNV);
+    DeclareKindCase(TensorLayoutNV);
+    DeclareKindCase(TensorViewNV);
 #undef DeclareKindCase
     default:
       assert(false && "Unhandled type");
@@ -747,7 +751,55 @@ bool CooperativeMatrixKHR::IsSameImpl(const Type* that,
   if (!mt) return false;
   return component_type_->IsSameImpl(mt->component_type_, seen) &&
          scope_id_ == mt->scope_id_ && rows_id_ == mt->rows_id_ &&
-         columns_id_ == mt->columns_id_ && HasSameDecorations(that);
+         columns_id_ == mt->columns_id_ && use_id_ == mt->use_id_ &&
+         HasSameDecorations(that);
+}
+
+TensorLayoutNV::TensorLayoutNV(const uint32_t dim, const uint32_t clamp_mode)
+    : Type(kTensorLayoutNV), dim_id_(dim), clamp_mode_id_(clamp_mode) {}
+
+std::string TensorLayoutNV::str() const {
+  std::ostringstream oss;
+  oss << "<" << dim_id_ << ", " << clamp_mode_id_ << ">";
+  return oss.str();
+}
+
+size_t TensorLayoutNV::ComputeExtraStateHash(size_t hash, SeenTypes*) const {
+  return hash_combine(hash, dim_id_, clamp_mode_id_);
+}
+
+bool TensorLayoutNV::IsSameImpl(const Type* that, IsSameCache*) const {
+  const TensorLayoutNV* tl = that->AsTensorLayoutNV();
+  if (!tl) return false;
+  return dim_id_ == tl->dim_id_ && clamp_mode_id_ == tl->clamp_mode_id_;
+}
+
+TensorViewNV::TensorViewNV(const uint32_t dim, const uint32_t clamp_mode,
+                           const std::vector<uint32_t>& perm)
+    : Type(kTensorViewNV),
+      dim_id_(dim),
+      has_dimensions_id_(clamp_mode),
+      perm_(perm) {}
+
+std::string TensorViewNV::str() const {
+  std::ostringstream oss;
+  oss << "<" << dim_id_ << ", " << has_dimensions_id_;
+  for (auto p : perm_) {
+    oss << ", " << p;
+  }
+  oss << ">";
+  return oss.str();
+}
+
+size_t TensorViewNV::ComputeExtraStateHash(size_t hash, SeenTypes*) const {
+  return hash_combine(hash, dim_id_, has_dimensions_id_, perm_);
+}
+
+bool TensorViewNV::IsSameImpl(const Type* that, IsSameCache*) const {
+  const TensorViewNV* tv = that->AsTensorViewNV();
+  if (!tv) return false;
+  return dim_id_ == tv->dim_id_ &&
+         has_dimensions_id_ == tv->has_dimensions_id_ && perm_ == tv->perm_;
 }
 
 }  // namespace analysis

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

@@ -63,6 +63,8 @@ class CooperativeMatrixNV;
 class CooperativeMatrixKHR;
 class RayQueryKHR;
 class HitObjectNV;
+class TensorLayoutNV;
+class TensorViewNV;
 
 // Abstract class for a SPIR-V type. It has a bunch of As<sublcass>() methods,
 // which is used as a way to probe the actual <subclass>.
@@ -104,6 +106,8 @@ class Type {
     kCooperativeMatrixKHR,
     kRayQueryKHR,
     kHitObjectNV,
+    kTensorLayoutNV,
+    kTensorViewNV,
     kLast
   };
 
@@ -206,6 +210,8 @@ class Type {
   DeclareCastMethod(CooperativeMatrixKHR)
   DeclareCastMethod(RayQueryKHR)
   DeclareCastMethod(HitObjectNV)
+  DeclareCastMethod(TensorLayoutNV)
+  DeclareCastMethod(TensorViewNV)
 #undef DeclareCastMethod
 
 protected:
@@ -659,6 +665,53 @@ class CooperativeMatrixKHR : public Type {
   const uint32_t use_id_;
 };
 
+class TensorLayoutNV : public Type {
+ public:
+  TensorLayoutNV(const uint32_t dim, const uint32_t clamp_mode);
+  TensorLayoutNV(const TensorLayoutNV&) = default;
+
+  std::string str() const override;
+
+  TensorLayoutNV* AsTensorLayoutNV() override { return this; }
+  const TensorLayoutNV* AsTensorLayoutNV() const override { return this; }
+
+  size_t ComputeExtraStateHash(size_t hash, SeenTypes* seen) const override;
+
+  uint32_t dim_id() const { return dim_id_; }
+  uint32_t clamp_mode_id() const { return clamp_mode_id_; }
+
+ private:
+  bool IsSameImpl(const Type* that, IsSameCache*) const override;
+
+  const uint32_t dim_id_;
+  const uint32_t clamp_mode_id_;
+};
+
+class TensorViewNV : public Type {
+ public:
+  TensorViewNV(const uint32_t dim, const uint32_t clamp_mode,
+               const std::vector<uint32_t>& perm);
+  TensorViewNV(const TensorViewNV&) = default;
+
+  std::string str() const override;
+
+  TensorViewNV* AsTensorViewNV() override { return this; }
+  const TensorViewNV* AsTensorViewNV() const override { return this; }
+
+  size_t ComputeExtraStateHash(size_t hash, SeenTypes* seen) const override;
+
+  uint32_t dim_id() const { return dim_id_; }
+  uint32_t has_dimensions_id() const { return has_dimensions_id_; }
+  const std::vector<uint32_t>& perm() const { return perm_; }
+
+ private:
+  bool IsSameImpl(const Type* that, IsSameCache*) const override;
+
+  const uint32_t dim_id_;
+  const uint32_t has_dimensions_id_;
+  std::vector<uint32_t> perm_;
+};
+
 #define DefineParameterlessType(type, name)                                \
   class type : public Type {                                               \
    public:                                                                 \

+ 7 - 26
3rdparty/spirv-tools/source/print.cpp

@@ -14,26 +14,7 @@
 
 #include "source/print.h"
 
-#if defined(SPIRV_ANDROID) || defined(SPIRV_LINUX) || defined(SPIRV_MAC) || \
-    defined(SPIRV_IOS) || defined(SPIRV_TVOS) || defined(SPIRV_FREEBSD) ||  \
-    defined(SPIRV_OPENBSD) || defined(SPIRV_EMSCRIPTEN) ||                  \
-    defined(SPIRV_FUCHSIA) || defined(SPIRV_GNU) || defined(SPIRV_QNX)
-namespace spvtools {
-
-clr::reset::operator const char*() { return "\x1b[0m"; }
-
-clr::grey::operator const char*() { return "\x1b[1;30m"; }
-
-clr::red::operator const char*() { return "\x1b[31m"; }
-
-clr::green::operator const char*() { return "\x1b[32m"; }
-
-clr::yellow::operator const char*() { return "\x1b[33m"; }
-
-clr::blue::operator const char*() { return "\x1b[34m"; }
-
-}  // namespace spvtools
-#elif defined(SPIRV_WINDOWS)
+#if defined(SPIRV_WINDOWS)
 #include <windows.h>
 
 namespace spvtools {
@@ -111,17 +92,17 @@ clr::blue::operator const char*() {
 #else
 namespace spvtools {
 
-clr::reset::operator const char*() { return ""; }
+clr::reset::operator const char*() { return "\x1b[0m"; }
 
-clr::grey::operator const char*() { return ""; }
+clr::grey::operator const char*() { return "\x1b[1;30m"; }
 
-clr::red::operator const char*() { return ""; }
+clr::red::operator const char*() { return "\x1b[31m"; }
 
-clr::green::operator const char*() { return ""; }
+clr::green::operator const char*() { return "\x1b[32m"; }
 
-clr::yellow::operator const char*() { return ""; }
+clr::yellow::operator const char*() { return "\x1b[33m"; }
 
-clr::blue::operator const char*() { return ""; }
+clr::blue::operator const char*() { return "\x1b[34m"; }
 
 }  // namespace spvtools
 #endif

+ 105 - 29
3rdparty/spirv-tools/source/spirv_target_env.cpp

@@ -14,11 +14,13 @@
 
 #include "source/spirv_target_env.h"
 
+#include <array>
 #include <cassert>
+#include <cctype>
 #include <cstring>
 #include <string>
-#include <utility>
 
+#include "source/latest_version_spirv_header.h"
 #include "source/spirv_constant.h"
 #include "spirv-tools/libspirv.h"
 
@@ -77,6 +79,8 @@ const char* spvTargetEnvDescription(spv_target_env env) {
       return "SPIR-V 1.6";
     case SPV_ENV_VULKAN_1_3:
       return "SPIR-V 1.6 (under Vulkan 1.3 semantics)";
+    case SPV_ENV_VULKAN_1_4:
+      return "SPIR-V 1.6 (under Vulkan 1.4 semantics)";
     case SPV_ENV_MAX:
       assert(false && "Invalid target environment value.");
       break;
@@ -120,6 +124,7 @@ uint32_t spvVersionForTargetEnv(spv_target_env env) {
       return SPV_SPIRV_VERSION_WORD(1, 5);
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return SPV_SPIRV_VERSION_WORD(1, 6);
     case SPV_ENV_MAX:
       assert(false && "Invalid target environment value.");
@@ -128,32 +133,44 @@ uint32_t spvVersionForTargetEnv(spv_target_env env) {
   return SPV_SPIRV_VERSION_WORD(0, 0);
 }
 
-static const std::pair<const char*, spv_target_env> spvTargetEnvNameMap[] = {
-    {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4},
-    {"vulkan1.0", SPV_ENV_VULKAN_1_0},
-    {"vulkan1.1", SPV_ENV_VULKAN_1_1},
-    {"vulkan1.2", SPV_ENV_VULKAN_1_2},
-    {"vulkan1.3", SPV_ENV_VULKAN_1_3},
-    {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
-    {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
-    {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
-    {"spv1.3", SPV_ENV_UNIVERSAL_1_3},
-    {"spv1.4", SPV_ENV_UNIVERSAL_1_4},
-    {"spv1.5", SPV_ENV_UNIVERSAL_1_5},
-    {"spv1.6", SPV_ENV_UNIVERSAL_1_6},
-    {"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
-    {"opencl1.2", SPV_ENV_OPENCL_1_2},
-    {"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
-    {"opencl2.0", SPV_ENV_OPENCL_2_0},
-    {"opencl2.1embedded", SPV_ENV_OPENCL_EMBEDDED_2_1},
-    {"opencl2.1", SPV_ENV_OPENCL_2_1},
-    {"opencl2.2embedded", SPV_ENV_OPENCL_EMBEDDED_2_2},
-    {"opencl2.2", SPV_ENV_OPENCL_2_2},
-    {"opengl4.0", SPV_ENV_OPENGL_4_0},
-    {"opengl4.1", SPV_ENV_OPENGL_4_1},
-    {"opengl4.2", SPV_ENV_OPENGL_4_2},
-    {"opengl4.3", SPV_ENV_OPENGL_4_3},
-    {"opengl4.5", SPV_ENV_OPENGL_4_5},
+// When a new SPIR-V version is released, update this table.
+static_assert(spv::Version == 0x10600);
+constexpr auto ordered_universal_envs = std::array<spv_target_env, 7>{
+    SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_UNIVERSAL_1_2,
+    SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4, SPV_ENV_UNIVERSAL_1_5,
+    SPV_ENV_UNIVERSAL_1_6,
+};
+
+// When a new SPIR-V version is released, update this table.
+static_assert(spv::Version == 0x10600);
+inline constexpr std::pair<const char*, spv_target_env> spvTargetEnvNameMap[] =
+    {
+        {"vulkan1.1spv1.4", SPV_ENV_VULKAN_1_1_SPIRV_1_4},
+        {"vulkan1.0", SPV_ENV_VULKAN_1_0},
+        {"vulkan1.1", SPV_ENV_VULKAN_1_1},
+        {"vulkan1.2", SPV_ENV_VULKAN_1_2},
+        {"vulkan1.3", SPV_ENV_VULKAN_1_3},
+        {"vulkan1.4", SPV_ENV_VULKAN_1_4},
+        {"spv1.0", SPV_ENV_UNIVERSAL_1_0},
+        {"spv1.1", SPV_ENV_UNIVERSAL_1_1},
+        {"spv1.2", SPV_ENV_UNIVERSAL_1_2},
+        {"spv1.3", SPV_ENV_UNIVERSAL_1_3},
+        {"spv1.4", SPV_ENV_UNIVERSAL_1_4},
+        {"spv1.5", SPV_ENV_UNIVERSAL_1_5},
+        {"spv1.6", SPV_ENV_UNIVERSAL_1_6},
+        {"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
+        {"opencl1.2", SPV_ENV_OPENCL_1_2},
+        {"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
+        {"opencl2.0", SPV_ENV_OPENCL_2_0},
+        {"opencl2.1embedded", SPV_ENV_OPENCL_EMBEDDED_2_1},
+        {"opencl2.1", SPV_ENV_OPENCL_2_1},
+        {"opencl2.2embedded", SPV_ENV_OPENCL_EMBEDDED_2_2},
+        {"opencl2.2", SPV_ENV_OPENCL_2_2},
+        {"opengl4.0", SPV_ENV_OPENGL_4_0},
+        {"opengl4.1", SPV_ENV_OPENGL_4_1},
+        {"opengl4.2", SPV_ENV_OPENGL_4_2},
+        {"opengl4.3", SPV_ENV_OPENGL_4_3},
+        {"opengl4.5", SPV_ENV_OPENGL_4_5},
 };
 
 bool spvParseTargetEnv(const char* s, spv_target_env* env) {
@@ -172,6 +189,59 @@ bool spvParseTargetEnv(const char* s, spv_target_env* env) {
   return false;
 }
 
+bool spvReadEnvironmentFromText(const std::vector<char>& text,
+                                spv_target_env* env) {
+  // Version is expected to match "; Version: 1.X"
+  // Version string must occur in header, that is, initial lines of comments
+  // Once a non-comment line occurs, the header has ended
+  for (std::size_t i = 0; i < text.size(); ++i) {
+    char c = text[i];
+
+    if (c == ';') {
+      // Try to match against the expected version string
+      constexpr const char* kVersionPrefix = "; Version: 1.";
+      constexpr const auto kPrefixLength = 13;
+      // 'minor_digit_pos' is the expected position of the version digit.
+      const auto minor_digit_pos = i + kPrefixLength;
+      if (minor_digit_pos >= text.size()) return false;
+
+      // Match the prefix.
+      auto j = 1;
+      for (; j < kPrefixLength; ++j) {
+        if (kVersionPrefix[j] != text[i + j]) break;
+      }
+      // j will match the prefix length if all characters before matched
+      if (j == kPrefixLength) {
+        // This expects only one digit in the minor number.
+        static_assert(((spv::Version >> 8) & 0xff) < 10);
+        char minor = text[minor_digit_pos];
+        char next_char =
+            minor_digit_pos + 1 < text.size() ? text[minor_digit_pos + 1] : 0;
+        if (std::isdigit(minor) && !std::isdigit(next_char)) {
+          const auto index = minor - '0';
+          assert(index >= 0);
+          if (static_cast<size_t>(index) < ordered_universal_envs.size()) {
+            *env = ordered_universal_envs[index];
+            return true;
+          }
+        }
+      }
+
+      // If no match, determine whether the header has ended (in which case,
+      // assumption has failed.)
+      // Skip until the next line.
+      i += j;
+      for (; i < text.size(); ++i) {
+        if (text[i] == '\n') break;
+      }
+    } else if (!std::isspace(c)) {
+      // Allow blanks, but end the search if we find something else.
+      break;
+    }
+  }
+  return false;
+}
+
 #define VULKAN_VER(MAJOR, MINOR) ((MAJOR << 22) | (MINOR << 12))
 #define SPIRV_VER(MAJOR, MINOR) ((MAJOR << 16) | (MINOR << 8))
 
@@ -188,7 +258,8 @@ static const VulkanEnv ordered_vulkan_envs[] = {
     {SPV_ENV_VULKAN_1_1, VULKAN_VER(1, 1), SPIRV_VER(1, 3)},
     {SPV_ENV_VULKAN_1_1_SPIRV_1_4, VULKAN_VER(1, 1), SPIRV_VER(1, 4)},
     {SPV_ENV_VULKAN_1_2, VULKAN_VER(1, 2), SPIRV_VER(1, 5)},
-    {SPV_ENV_VULKAN_1_3, VULKAN_VER(1, 3), SPIRV_VER(1, 6)}};
+    {SPV_ENV_VULKAN_1_3, VULKAN_VER(1, 3), SPIRV_VER(1, 6)},
+    {SPV_ENV_VULKAN_1_4, VULKAN_VER(1, 4), SPIRV_VER(1, 6)}};
 
 bool spvParseVulkanEnv(uint32_t vulkan_ver, uint32_t spirv_ver,
                        spv_target_env* env) {
@@ -229,6 +300,7 @@ bool spvIsVulkanEnv(spv_target_env env) {
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return true;
     case SPV_ENV_WEBGPU_0:
       assert(false && "Deprecated target environment value.");
@@ -259,6 +331,7 @@ bool spvIsOpenCLEnv(spv_target_env env) {
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return false;
     case SPV_ENV_OPENCL_1_2:
     case SPV_ENV_OPENCL_EMBEDDED_1_2:
@@ -301,6 +374,7 @@ bool spvIsOpenGLEnv(spv_target_env env) {
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       return false;
     case SPV_ENV_OPENGL_4_0:
     case SPV_ENV_OPENGL_4_1:
@@ -340,6 +414,7 @@ bool spvIsValidEnv(spv_target_env env) {
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
     case SPV_ENV_OPENGL_4_0:
     case SPV_ENV_OPENGL_4_1:
     case SPV_ENV_OPENGL_4_2:
@@ -376,7 +451,8 @@ std::string spvLogStringForEnv(spv_target_env env) {
     case SPV_ENV_VULKAN_1_1:
     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
     case SPV_ENV_VULKAN_1_2:
-    case SPV_ENV_VULKAN_1_3: {
+    case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4: {
       return "Vulkan";
     }
     case SPV_ENV_UNIVERSAL_1_0:

+ 7 - 0
3rdparty/spirv-tools/source/spirv_target_env.h

@@ -16,6 +16,8 @@
 #define SOURCE_SPIRV_TARGET_ENV_H_
 
 #include <string>
+#include <utility>
+#include <vector>
 
 #include "spirv-tools/libspirv.h"
 
@@ -46,4 +48,9 @@ std::string spvLogStringForEnv(spv_target_env env);
 //        occur to satisfy this limit.
 std::string spvTargetEnvList(const int pad, const int wrap);
 
+// Reads the target environment from the header comments of disassembly. Returns
+// true if valid name found, false otherwise.
+bool spvReadEnvironmentFromText(const std::vector<char>& text,
+                                spv_target_env* env);
+
 #endif  // SOURCE_SPIRV_TARGET_ENV_H_

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

@@ -43,6 +43,7 @@ spv_context spvContextCreate(spv_target_env env) {
     case SPV_ENV_VULKAN_1_2:
     case SPV_ENV_UNIVERSAL_1_6:
     case SPV_ENV_VULKAN_1_3:
+    case SPV_ENV_VULKAN_1_4:
       break;
     default:
       return nullptr;

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

@@ -201,7 +201,7 @@ spv_result_t spvTextEncodeOperand(const spvtools::AssemblyGrammar& grammar,
   }
 
   // Optional literal operands can fail to parse. In that case use
-  // SPV_FAILED_MATCH to avoid emitting a diagostic.  Use the following
+  // SPV_FAILED_MATCH to avoid emitting a diagnostic.  Use the following
   // for those situations.
   spv_result_t error_code_for_literals =
       spvOperandIsOptional(type) ? SPV_FAILED_MATCH : SPV_ERROR_INVALID_TEXT;
@@ -414,7 +414,9 @@ spv_result_t spvTextEncodeOperand(const spvtools::AssemblyGrammar& grammar,
     case SPV_OPERAND_TYPE_SELECTION_CONTROL:
     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
-    case SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS: {
+    case SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS:
+    case SPV_OPERAND_TYPE_TENSOR_ADDRESSING_OPERANDS:
+    case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE: {
       uint32_t value;
       if (auto error = grammar.parseMaskOperand(type, textValue, &value)) {
         return context->diagnostic(error)

+ 2 - 1
3rdparty/spirv-tools/source/val/function.h

@@ -20,6 +20,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <type_traits>
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
@@ -278,7 +279,7 @@ class Function {
   Construct& FindConstructForEntryBlock(const BasicBlock* entry_block,
                                         ConstructType t);
 
-  /// The result id of the OpLabel that defined this block
+  /// The result id of OpFunction
   uint32_t id_;
 
   /// The type of the function

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

@@ -366,6 +366,7 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
     if (auto error = RayTracingPass(*vstate, &instruction)) return error;
     if (auto error = RayReorderNVPass(*vstate, &instruction)) return error;
     if (auto error = MeshShadingPass(*vstate, &instruction)) return error;
+    if (auto error = TensorLayoutPass(*vstate, &instruction)) return error;
   }
 
   // Validate the preconditions involving adjacent instructions. e.g.

+ 3 - 0
3rdparty/spirv-tools/source/val/validate.h

@@ -226,6 +226,9 @@ spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst);
 /// Calculates the reachability of basic blocks.
 void ReachabilityPass(ValidationState_t& _);
 
+/// Validates tensor layout and view instructions.
+spv_result_t TensorLayoutPass(ValidationState_t& _, const Instruction* inst);
+
 /// Validates execution limitations.
 ///
 /// Verifies execution models are allowed for all functionality they contain.

+ 125 - 3
3rdparty/spirv-tools/source/val/validate_arithmetics.cpp

@@ -62,7 +62,7 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) {
                    << operand_index;
           }
           spv_result_t ret =
-              _.CooperativeMatrixShapesMatch(inst, type_id, result_type);
+              _.CooperativeMatrixShapesMatch(inst, result_type, type_id, false);
           if (ret != SPV_SUCCESS) return ret;
         } else if (_.GetOperandTypeId(inst, operand_index) != result_type)
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -96,7 +96,7 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) {
                    << operand_index;
           }
           spv_result_t ret =
-              _.CooperativeMatrixShapesMatch(inst, type_id, result_type);
+              _.CooperativeMatrixShapesMatch(inst, result_type, type_id, false);
           if (ret != SPV_SUCCESS) return ret;
         } else if (_.GetOperandTypeId(inst, operand_index) != result_type)
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -142,7 +142,7 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) {
                    << operand_index;
           }
           spv_result_t ret =
-              _.CooperativeMatrixShapesMatch(inst, type_id, result_type);
+              _.CooperativeMatrixShapesMatch(inst, result_type, type_id, false);
           if (ret != SPV_SUCCESS) return ret;
         }
 
@@ -672,6 +672,128 @@ spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) {
       break;
     }
 
+    case spv::Op::OpCooperativeMatrixReduceNV: {
+      if (!_.IsCooperativeMatrixKHRType(result_type)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Result Type must be a cooperative matrix type: "
+               << spvOpcodeString(opcode);
+      }
+
+      const auto result_comp_type_id =
+          _.FindDef(result_type)->GetOperandAs<uint32_t>(1);
+
+      const auto matrix_id = inst->GetOperandAs<uint32_t>(2);
+      const auto matrix = _.FindDef(matrix_id);
+      const auto matrix_type_id = matrix->type_id();
+      if (!_.IsCooperativeMatrixKHRType(matrix_type_id)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Matrix must have a cooperative matrix type: "
+               << spvOpcodeString(opcode);
+      }
+      const auto matrix_type = _.FindDef(matrix_type_id);
+      const auto matrix_comp_type_id = matrix_type->GetOperandAs<uint32_t>(1);
+      if (matrix_comp_type_id != result_comp_type_id) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Result Type and Matrix type must have the same component "
+                  "type: "
+               << spvOpcodeString(opcode);
+      }
+      if (_.FindDef(result_type)->GetOperandAs<uint32_t>(2) !=
+          matrix_type->GetOperandAs<uint32_t>(2)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Result Type and Matrix type must have the same scope: "
+               << spvOpcodeString(opcode);
+      }
+
+      if (!_.IsCooperativeMatrixAccType(result_type)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Result Type must have UseAccumulator: "
+               << spvOpcodeString(opcode);
+      }
+      if (!_.IsCooperativeMatrixAccType(matrix_type_id)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Matrix type must have UseAccumulator: "
+               << spvOpcodeString(opcode);
+      }
+
+      const auto reduce_value = inst->GetOperandAs<uint32_t>(3);
+
+      if ((reduce_value &
+           uint32_t(
+               spv::CooperativeMatrixReduceMask::CooperativeMatrixReduce2x2)) &&
+          (reduce_value & uint32_t(spv::CooperativeMatrixReduceMask::Row |
+                                   spv::CooperativeMatrixReduceMask::Column))) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Reduce 2x2 must not be used with Row/Column: "
+               << spvOpcodeString(opcode);
+      }
+
+      std::tuple<bool, bool, uint32_t> result_rows, result_cols, matrix_rows,
+          matrix_cols;
+      result_rows =
+          _.EvalInt32IfConst(_.FindDef(result_type)->GetOperandAs<uint32_t>(3));
+      result_cols =
+          _.EvalInt32IfConst(_.FindDef(result_type)->GetOperandAs<uint32_t>(4));
+      matrix_rows = _.EvalInt32IfConst(matrix_type->GetOperandAs<uint32_t>(3));
+      matrix_cols = _.EvalInt32IfConst(matrix_type->GetOperandAs<uint32_t>(4));
+
+      if (reduce_value &
+          uint32_t(
+              spv::CooperativeMatrixReduceMask::CooperativeMatrixReduce2x2)) {
+        if (std::get<1>(result_rows) && std::get<1>(result_cols) &&
+            std::get<1>(matrix_rows) && std::get<1>(matrix_cols) &&
+            (std::get<2>(result_rows) != std::get<2>(matrix_rows) / 2 ||
+             std::get<2>(result_cols) != std::get<2>(matrix_cols) / 2)) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "For Reduce2x2, result rows/cols must be half of matrix "
+                    "rows/cols: "
+                 << spvOpcodeString(opcode);
+        }
+      }
+      if (reduce_value == uint32_t(spv::CooperativeMatrixReduceMask::Row)) {
+        if (std::get<1>(result_rows) && std::get<1>(matrix_rows) &&
+            std::get<2>(result_rows) != std::get<2>(matrix_rows)) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "For ReduceRow, result rows must match matrix rows: "
+                 << spvOpcodeString(opcode);
+        }
+      }
+      if (reduce_value == uint32_t(spv::CooperativeMatrixReduceMask::Column)) {
+        if (std::get<1>(result_cols) && std::get<1>(matrix_cols) &&
+            std::get<2>(result_cols) != std::get<2>(matrix_cols)) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "For ReduceColumn, result cols must match matrix cols: "
+                 << spvOpcodeString(opcode);
+        }
+      }
+
+      const auto combine_func_id = inst->GetOperandAs<uint32_t>(4);
+      const auto combine_func = _.FindDef(combine_func_id);
+      if (!combine_func || combine_func->opcode() != spv::Op::OpFunction) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "CombineFunc must be a function: " << spvOpcodeString(opcode);
+      }
+      const auto function_type_id = combine_func->GetOperandAs<uint32_t>(3);
+      const auto function_type = _.FindDef(function_type_id);
+      if (function_type->operands().size() != 4) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "CombineFunc must have two parameters: "
+               << spvOpcodeString(opcode);
+      }
+      for (uint32_t i = 0; i < 3; ++i) {
+        // checks return type and two params
+        const auto param_type_id = function_type->GetOperandAs<uint32_t>(i + 1);
+        if (param_type_id != matrix_comp_type_id) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "CombineFunc return type and parameters must match matrix "
+                    "component type: "
+                 << spvOpcodeString(opcode);
+        }
+      }
+
+      break;
+    }
+
     default:
       break;
   }

+ 45 - 8
3rdparty/spirv-tools/source/val/validate_conversion.cpp

@@ -49,7 +49,7 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
       if (_.IsCooperativeMatrixType(result_type) ||
           _.IsCooperativeMatrixType(input_type)) {
         spv_result_t ret =
-            _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
+            _.CooperativeMatrixShapesMatch(inst, result_type, input_type, true);
         if (ret != SPV_SUCCESS) return ret;
       } else {
         if (_.GetDimension(result_type) != _.GetDimension(input_type))
@@ -79,7 +79,7 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
       if (_.IsCooperativeMatrixType(result_type) ||
           _.IsCooperativeMatrixType(input_type)) {
         spv_result_t ret =
-            _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
+            _.CooperativeMatrixShapesMatch(inst, result_type, input_type, true);
         if (ret != SPV_SUCCESS) return ret;
       } else {
         if (_.GetDimension(result_type) != _.GetDimension(input_type))
@@ -111,7 +111,7 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
       if (_.IsCooperativeMatrixType(result_type) ||
           _.IsCooperativeMatrixType(input_type)) {
         spv_result_t ret =
-            _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
+            _.CooperativeMatrixShapesMatch(inst, result_type, input_type, true);
         if (ret != SPV_SUCCESS) return ret;
       } else {
         if (_.GetDimension(result_type) != _.GetDimension(input_type))
@@ -142,7 +142,7 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
       if (_.IsCooperativeMatrixType(result_type) ||
           _.IsCooperativeMatrixType(input_type)) {
         spv_result_t ret =
-            _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
+            _.CooperativeMatrixShapesMatch(inst, result_type, input_type, true);
         if (ret != SPV_SUCCESS) return ret;
       } else {
         if (_.GetDimension(result_type) != _.GetDimension(input_type))
@@ -177,7 +177,7 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
       if (_.IsCooperativeMatrixType(result_type) ||
           _.IsCooperativeMatrixType(input_type)) {
         spv_result_t ret =
-            _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
+            _.CooperativeMatrixShapesMatch(inst, result_type, input_type, true);
         if (ret != SPV_SUCCESS) return ret;
       } else {
         if (_.GetDimension(result_type) != _.GetDimension(input_type))
@@ -213,7 +213,7 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
       if (_.IsCooperativeMatrixType(result_type) ||
           _.IsCooperativeMatrixType(input_type)) {
         spv_result_t ret =
-            _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
+            _.CooperativeMatrixShapesMatch(inst, result_type, input_type, true);
         if (ret != SPV_SUCCESS) return ret;
       } else {
         if (_.GetDimension(result_type) != _.GetDimension(input_type))
@@ -497,8 +497,8 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
                << "matrix: " << spvOpcodeString(opcode);
 
       if (result_is_coopmat) {
-        spv_result_t ret =
-            _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
+        spv_result_t ret = _.CooperativeMatrixShapesMatch(inst, result_type,
+                                                          input_type, false);
         if (ret != SPV_SUCCESS) return ret;
       }
 
@@ -568,6 +568,43 @@ spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
       break;
     }
 
+    case spv::Op::OpCooperativeMatrixConvertNV:
+    case spv::Op::OpCooperativeMatrixTransposeNV: {
+      if (!_.IsCooperativeMatrixType(result_type)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Expected cooperative matrix Result Type: "
+               << spvOpcodeString(opcode);
+      }
+      const uint32_t input_type = _.GetOperandTypeId(inst, 2);
+      if (!_.IsCooperativeMatrixType(input_type)) {
+        return _.diag(SPV_ERROR_INVALID_DATA, inst)
+               << "Expected cooperative matrix type for Matrix input: "
+               << spvOpcodeString(opcode);
+      }
+
+      bool swap_row_col = (opcode == spv::Op::OpCooperativeMatrixTransposeNV);
+      if (auto error = _.CooperativeMatrixShapesMatch(
+              inst, result_type, input_type, true, swap_row_col))
+        return error;
+
+      if (opcode == spv::Op::OpCooperativeMatrixConvertNV) {
+        if (_.FindDef(result_type)->GetOperandAs<uint32_t>(1) !=
+            _.FindDef(input_type)->GetOperandAs<uint32_t>(1)) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Result Type and Matrix component types mismatch: "
+                 << spvOpcodeString(opcode);
+        }
+      }
+
+      if (opcode == spv::Op::OpCooperativeMatrixTransposeNV) {
+        if (!_.IsCooperativeMatrixBType(result_type)) {
+          return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                 << "Result Type must have UseB: " << spvOpcodeString(opcode);
+        }
+      }
+      break;
+    }
+
     default:
       break;
   }

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

@@ -169,7 +169,7 @@ uint32_t getBaseAlignment(uint32_t member_id, bool roundUp,
     case spv::Op::OpTypeSampler:
     case spv::Op::OpTypeImage:
       if (vstate.HasCapability(spv::Capability::BindlessTextureNV))
-        return baseAlignment = vstate.samplerimage_variable_address_mode() / 8;
+        return vstate.samplerimage_variable_address_mode() / 8;
       assert(0);
       return 0;
     case spv::Op::OpTypeInt:

+ 97 - 27
3rdparty/spirv-tools/source/val/validate_extensions.cpp

@@ -3090,7 +3090,6 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
         // validation.
         case NonSemanticShaderDebugInfo100DebugInfoNone:
         case NonSemanticShaderDebugInfo100DebugCompilationUnit:
-        case NonSemanticShaderDebugInfo100DebugTypeBasic:
         case NonSemanticShaderDebugInfo100DebugTypePointer:
         case NonSemanticShaderDebugInfo100DebugTypeQualifier:
         case NonSemanticShaderDebugInfo100DebugTypeArray:
@@ -3116,7 +3115,6 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
         case NonSemanticShaderDebugInfo100DebugInlinedAt:
         case NonSemanticShaderDebugInfo100DebugLocalVariable:
         case NonSemanticShaderDebugInfo100DebugInlinedVariable:
-        case NonSemanticShaderDebugInfo100DebugDeclare:
         case NonSemanticShaderDebugInfo100DebugValue:
         case NonSemanticShaderDebugInfo100DebugOperation:
         case NonSemanticShaderDebugInfo100DebugExpression:
@@ -3125,6 +3123,24 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
         case NonSemanticShaderDebugInfo100DebugImportedEntity:
         case NonSemanticShaderDebugInfo100DebugSource:
           break;
+
+        // These checks are for operands that are differnet in
+        // ShaderDebugInfo100
+        case NonSemanticShaderDebugInfo100DebugTypeBasic: {
+          CHECK_CONST_UINT_OPERAND("Flags", 8);
+          break;
+        }
+        case NonSemanticShaderDebugInfo100DebugDeclare: {
+          for (uint32_t word_index = 8; word_index < num_words; ++word_index) {
+            auto index_inst = _.FindDef(inst->word(word_index));
+            auto type_id = index_inst != nullptr ? index_inst->type_id() : 0;
+            if (type_id == 0 || !IsIntScalar(_, type_id, false, false))
+              return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                     << ext_inst_name() << ": "
+                     << "expected index must be scalar integer";
+          }
+          break;
+        }
         case NonSemanticShaderDebugInfo100DebugTypeMatrix: {
           CHECK_DEBUG_OPERAND("Vector Type", CommonDebugInfoDebugTypeVector, 5);
 
@@ -3146,14 +3162,84 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
           }
           break;
         }
-        // TODO: Add validation rules for remaining cases as well.
-        case NonSemanticShaderDebugInfo100DebugFunctionDefinition:
-        case NonSemanticShaderDebugInfo100DebugSourceContinued:
-        case NonSemanticShaderDebugInfo100DebugLine:
+        case NonSemanticShaderDebugInfo100DebugFunctionDefinition: {
+          CHECK_DEBUG_OPERAND("Function", CommonDebugInfoDebugFunction, 5);
+          CHECK_OPERAND("Definition", spv::Op::OpFunction, 6);
+          const auto* current_function = inst->function();
+          if (current_function->first_block()->id() != inst->block()->id()) {
+            return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                   << ext_inst_name()
+                   << ": must be in the entry basic block of the function";
+          }
+
+          const uint32_t definition_id = inst->word(6);
+          if (definition_id != current_function->id()) {
+            return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                   << ext_inst_name()
+                   << ": operand Definition must point to the OpFunction it is "
+                      "inside";
+          }
+          break;
+        }
+        case NonSemanticShaderDebugInfo100DebugLine: {
+          CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 5);
+          CHECK_CONST_UINT_OPERAND("Line Start", 6);
+          CHECK_CONST_UINT_OPERAND("Line End", 7);
+          CHECK_CONST_UINT_OPERAND("Column Start", 8);
+          CHECK_CONST_UINT_OPERAND("Column End", 9);
+
+          // above already validates if 32-bit and non-spec constant
+          // but want to use EvalInt32IfConst to be consistent with other Eval
+          // locations
+          bool is_int32 = false, is_const_int32 = false;
+          uint32_t line_start = 0;
+          uint32_t line_end = 0;
+          uint32_t column_start = 0;
+          uint32_t column_end = 0;
+          std::tie(is_int32, is_const_int32, line_start) =
+              _.EvalInt32IfConst(inst->word(6));
+          std::tie(is_int32, is_const_int32, line_end) =
+              _.EvalInt32IfConst(inst->word(7));
+          std::tie(is_int32, is_const_int32, column_start) =
+              _.EvalInt32IfConst(inst->word(8));
+          std::tie(is_int32, is_const_int32, column_end) =
+              _.EvalInt32IfConst(inst->word(9));
+          if (line_end < line_start) {
+            return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                   << ext_inst_name() << ": operand Line End (" << line_end
+                   << ") is less than Line Start (" << line_start << ")";
+          } else if (line_start == line_end && column_end < column_start) {
+            return _.diag(SPV_ERROR_INVALID_DATA, inst)
+                   << ext_inst_name() << ": operand Column End (" << column_end
+                   << ") is less than Column Start (" << column_start
+                   << ") when Line Start equals Line End";
+          }
+          break;
+        }
+        case NonSemanticShaderDebugInfo100DebugSourceContinued: {
+          CHECK_OPERAND("Text", spv::Op::OpString, 5);
+          break;
+        }
+        case NonSemanticShaderDebugInfo100DebugBuildIdentifier: {
+          CHECK_OPERAND("Identifier", spv::Op::OpString, 5);
+          CHECK_CONST_UINT_OPERAND("Flags", 6);
+          break;
+        }
+        case NonSemanticShaderDebugInfo100DebugStoragePath: {
+          CHECK_OPERAND("Path", spv::Op::OpString, 5);
+          break;
+        }
+        case NonSemanticShaderDebugInfo100DebugEntryPoint: {
+          CHECK_DEBUG_OPERAND("Entry Point", CommonDebugInfoDebugFunction, 5);
+          CHECK_DEBUG_OPERAND("Compilation Unit",
+                              CommonDebugInfoDebugCompilationUnit, 6);
+          CHECK_OPERAND("Compiler Signature", spv::Op::OpString, 7);
+          CHECK_OPERAND("Command-line Arguments", spv::Op::OpString, 8);
+          break;
+        }
+
+          // Has no additional checks
         case NonSemanticShaderDebugInfo100DebugNoLine:
-        case NonSemanticShaderDebugInfo100DebugBuildIdentifier:
-        case NonSemanticShaderDebugInfo100DebugStoragePath:
-        case NonSemanticShaderDebugInfo100DebugEntryPoint:
           break;
         case NonSemanticShaderDebugInfo100InstructionsMax:
           assert(0);
@@ -3455,9 +3541,7 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
         }
         case CommonDebugInfoDebugFunction: {
           CHECK_OPERAND("Name", spv::Op::OpString, 5);
-          auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
-                                                        ext_inst_name, false);
-          if (validate_type != SPV_SUCCESS) return validate_type;
+          CHECK_DEBUG_OPERAND("Type", CommonDebugInfoDebugTypeFunction, 6);
           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
           CHECK_CONST_UINT_OPERAND("Line", 8);
           CHECK_CONST_UINT_OPERAND("Column", 9);
@@ -3492,9 +3576,7 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
         }
         case CommonDebugInfoDebugFunctionDeclaration: {
           CHECK_OPERAND("Name", spv::Op::OpString, 5);
-          auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
-                                                        ext_inst_name, false);
-          if (validate_type != SPV_SUCCESS) return validate_type;
+          CHECK_DEBUG_OPERAND("Type", CommonDebugInfoDebugTypeFunction, 6);
           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
           CHECK_CONST_UINT_OPERAND("Line", 8);
           CHECK_CONST_UINT_OPERAND("Column", 9);
@@ -3556,18 +3638,6 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
           }
 
           CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7);
-
-          if (vulkanDebugInfo) {
-            for (uint32_t word_index = 8; word_index < num_words;
-                 ++word_index) {
-              auto index_inst = _.FindDef(inst->word(word_index));
-              auto type_id = index_inst != nullptr ? index_inst->type_id() : 0;
-              if (type_id == 0 || !IsIntScalar(_, type_id, false, false))
-                return _.diag(SPV_ERROR_INVALID_DATA, inst)
-                       << ext_inst_name() << ": "
-                       << "expected index must be scalar integer";
-            }
-          }
           break;
         }
         case CommonDebugInfoDebugExpression: {

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

@@ -86,7 +86,10 @@ spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
       spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple,
       spv::Op::OpGetKernelLocalSizeForSubgroupCount,
       spv::Op::OpGetKernelMaxNumSubgroups,
-      spv::Op::OpName};
+      spv::Op::OpName,
+      spv::Op::OpCooperativeMatrixPerElementOpNV,
+      spv::Op::OpCooperativeMatrixReduceNV,
+      spv::Op::OpCooperativeMatrixLoadTensorNV};
   for (auto& pair : inst->uses()) {
     const auto* use = pair.first;
     if (std::find(acceptable.begin(), acceptable.end(), use->opcode()) ==
@@ -280,7 +283,7 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _,
         function_type->GetOperandAs<uint32_t>(param_index);
     const auto parameter_type = _.FindDef(parameter_type_id);
     if (!parameter_type || argument_type->id() != parameter_type->id()) {
-      if (!_.options()->before_hlsl_legalization ||
+      if (!parameter_type || !_.options()->before_hlsl_legalization ||
           !DoPointeesLogicallyMatch(argument_type, parameter_type, _)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "OpFunctionCall Argument <id> " << _.getIdName(argument_id)
@@ -341,6 +344,80 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _,
   return SPV_SUCCESS;
 }
 
+spv_result_t ValidateCooperativeMatrixPerElementOp(ValidationState_t& _,
+                                                   const Instruction* inst) {
+  const auto function_id = inst->GetOperandAs<uint32_t>(3);
+  const auto function = _.FindDef(function_id);
+  if (!function || spv::Op::OpFunction != function->opcode()) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV Function <id> "
+           << _.getIdName(function_id) << " is not a function.";
+  }
+
+  const auto matrix_id = inst->GetOperandAs<uint32_t>(2);
+  const auto matrix = _.FindDef(matrix_id);
+  const auto matrix_type_id = matrix->type_id();
+  if (!_.IsCooperativeMatrixKHRType(matrix_type_id)) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV Matrix <id> "
+           << _.getIdName(matrix_id) << " is not a cooperative matrix.";
+  }
+
+  const auto result_type_id = inst->GetOperandAs<uint32_t>(0);
+  if (matrix_type_id != result_type_id) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV Result Type <id> "
+           << _.getIdName(result_type_id) << " must match matrix type <id> "
+           << _.getIdName(matrix_type_id) << ".";
+  }
+
+  const auto matrix_comp_type_id =
+      _.FindDef(matrix_type_id)->GetOperandAs<uint32_t>(1);
+  const auto function_type_id = function->GetOperandAs<uint32_t>(3);
+  const auto function_type = _.FindDef(function_type_id);
+  auto return_type_id = function_type->GetOperandAs<uint32_t>(1);
+  if (return_type_id != matrix_comp_type_id) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV function return type <id> "
+           << _.getIdName(return_type_id)
+           << " must match matrix component type <id> "
+           << _.getIdName(matrix_comp_type_id) << ".";
+  }
+
+  if (function_type->operands().size() < 5) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV function type <id> "
+           << _.getIdName(function_type_id)
+           << " must have a least three parameters.";
+  }
+
+  const auto param0_id = function_type->GetOperandAs<uint32_t>(2);
+  const auto param1_id = function_type->GetOperandAs<uint32_t>(3);
+  const auto param2_id = function_type->GetOperandAs<uint32_t>(4);
+  if (!_.IsIntScalarType(param0_id) || _.GetBitWidth(param0_id) != 32) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV function type first parameter "
+              "type <id> "
+           << _.getIdName(param0_id) << " must be a 32-bit integer.";
+  }
+
+  if (!_.IsIntScalarType(param1_id) || _.GetBitWidth(param1_id) != 32) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV function type second "
+              "parameter type <id> "
+           << _.getIdName(param1_id) << " must be a 32-bit integer.";
+  }
+
+  if (param2_id != matrix_comp_type_id) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << "OpCooperativeMatrixPerElementOpNV function type third parameter "
+              "type <id> "
+           << _.getIdName(param2_id) << " must match matrix component type.";
+  }
+
+  return SPV_SUCCESS;
+}
+
 }  // namespace
 
 spv_result_t FunctionPass(ValidationState_t& _, const Instruction* inst) {
@@ -354,6 +431,10 @@ spv_result_t FunctionPass(ValidationState_t& _, const Instruction* inst) {
     case spv::Op::OpFunctionCall:
       if (auto error = ValidateFunctionCall(_, inst)) return error;
       break;
+    case spv::Op::OpCooperativeMatrixPerElementOpNV:
+      if (auto error = ValidateCooperativeMatrixPerElementOp(_, inst))
+        return error;
+      break;
     default:
       break;
   }

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

@@ -163,6 +163,7 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
               !spvOpcodeGeneratesType(opcode) && !spvOpcodeIsDebug(opcode) &&
               !inst->IsDebugInfo() && !inst->IsNonSemantic() &&
               !spvOpcodeIsDecoration(opcode) && opcode != spv::Op::OpFunction &&
+              opcode != spv::Op::OpSizeOf &&
               opcode != spv::Op::OpCooperativeMatrixLengthNV &&
               opcode != spv::Op::OpCooperativeMatrixLengthKHR &&
               !spvOpcodeGeneratesUntypedPointer(opcode) &&
@@ -185,6 +186,7 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
                      opcode != spv::Op::OpSelectionMerge &&
                      opcode != spv::Op::OpLoopMerge &&
                      opcode != spv::Op::OpFunction &&
+                     opcode != spv::Op::OpSizeOf &&
                      opcode != spv::Op::OpCooperativeMatrixLengthNV &&
                      opcode != spv::Op::OpCooperativeMatrixLengthKHR &&
                      !spvOpcodeGeneratesUntypedPointer(opcode) &&

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

@@ -994,6 +994,7 @@ bool IsAllowedSampledImageOperand(spv::Op opcode, ValidationState_t& _) {
     case spv::Op::OpImageBlockMatchWindowSSDQCOM:
     case spv::Op::OpImageBlockMatchGatherSADQCOM:
     case spv::Op::OpImageBlockMatchGatherSSDQCOM:
+    case spv::Op::OpImageSampleFootprintNV:
       return true;
     case spv::Op::OpStore:
       if (_.HasCapability(spv::Capability::BindlessTextureNV)) return true;

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

@@ -475,6 +475,12 @@ spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
     const uint32_t entry_point = inst->word(1);
     _.RegisterExecutionModeForEntryPoint(entry_point,
                                          spv::ExecutionMode(inst->word(2)));
+    if (inst->GetOperandAs<spv::ExecutionMode>(1) ==
+            spv::ExecutionMode::LocalSize ||
+        inst->GetOperandAs<spv::ExecutionMode>(1) ==
+            spv::ExecutionMode::LocalSizeId) {
+      _.RegisterEntryPointLocalSize(entry_point, inst);
+    }
   } else if (opcode == spv::Op::OpVariable) {
     const auto storage_class = inst->GetOperandAs<spv::StorageClass>(2);
     if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) {

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

@@ -75,8 +75,8 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _,
 
         if (local_debug_info) {
           if (_.in_function_body() == false) {
-            // DebugScope, DebugNoScope, DebugDeclare, DebugValue must
-            // appear in a function body.
+            // TODO - Print the actual name of the instruction as this list is
+            // not complete (see ext_inst_name in ValidateExtInst() for example)
             return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                    << "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
                    << "of debug info extension must appear in a function "

+ 236 - 9
3rdparty/spirv-tools/source/val/validate_memory.cpp

@@ -233,6 +233,7 @@ std::pair<spv::StorageClass, spv::StorageClass> GetStorageClass(
   spv::StorageClass src_sc = spv::StorageClass::Max;
   switch (inst->opcode()) {
     case spv::Op::OpCooperativeMatrixLoadNV:
+    case spv::Op::OpCooperativeMatrixLoadTensorNV:
     case spv::Op::OpCooperativeMatrixLoadKHR:
     case spv::Op::OpLoad: {
       auto load_pointer = _.FindDef(inst->GetOperandAs<uint32_t>(2));
@@ -241,6 +242,7 @@ std::pair<spv::StorageClass, spv::StorageClass> GetStorageClass(
       break;
     }
     case spv::Op::OpCooperativeMatrixStoreNV:
+    case spv::Op::OpCooperativeMatrixStoreTensorNV:
     case spv::Op::OpCooperativeMatrixStoreKHR:
     case spv::Op::OpStore: {
       auto store_pointer = _.FindDef(inst->GetOperandAs<uint32_t>(0));
@@ -330,6 +332,7 @@ spv_result_t CheckMemoryAccess(ValidationState_t& _, const Instruction* inst,
   if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) {
     if (inst->opcode() == spv::Op::OpLoad ||
         inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV ||
+        inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV ||
         inst->opcode() == spv::Op::OpCooperativeMatrixLoadKHR) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "MakePointerAvailableKHR cannot be used with OpLoad.";
@@ -350,7 +353,8 @@ spv_result_t CheckMemoryAccess(ValidationState_t& _, const Instruction* inst,
   if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) {
     if (inst->opcode() == spv::Op::OpStore ||
         inst->opcode() == spv::Op::OpCooperativeMatrixStoreNV ||
-        inst->opcode() == spv::Op::OpCooperativeMatrixStoreKHR) {
+        inst->opcode() == spv::Op::OpCooperativeMatrixStoreKHR ||
+        inst->opcode() == spv::Op::OpCooperativeMatrixStoreTensorNV) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "MakePointerVisibleKHR cannot be used with OpStore.";
     }
@@ -2111,14 +2115,16 @@ spv_result_t ValidateCooperativeMatrixLoadStoreKHR(ValidationState_t& _,
   const auto storage_class =
       pointer_type->GetOperandAs<spv::StorageClass>(storage_class_index);
 
-  if (storage_class != spv::StorageClass::Workgroup &&
-      storage_class != spv::StorageClass::StorageBuffer &&
-      storage_class != spv::StorageClass::PhysicalStorageBuffer) {
-    return _.diag(SPV_ERROR_INVALID_ID, inst)
-           << _.VkErrorID(8973) << opname
-           << " storage class for pointer type <id> "
-           << _.getIdName(pointer_type_id)
-           << " is not Workgroup, StorageBuffer, or PhysicalStorageBuffer.";
+  if (spvIsVulkanEnv(_.context()->target_env)) {
+    if (storage_class != spv::StorageClass::Workgroup &&
+        storage_class != spv::StorageClass::StorageBuffer &&
+        storage_class != spv::StorageClass::PhysicalStorageBuffer) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << _.VkErrorID(8973) << opname
+             << " storage class for pointer type <id> "
+             << _.getIdName(pointer_type_id)
+             << " is not Workgroup, StorageBuffer, or PhysicalStorageBuffer.";
+    }
   }
 
   if (!untyped) {
@@ -2176,6 +2182,222 @@ spv_result_t ValidateCooperativeMatrixLoadStoreKHR(ValidationState_t& _,
   return SPV_SUCCESS;
 }
 
+// Returns the number of instruction words taken up by a tensor addressing
+// operands argument and its implied operands.
+int TensorAddressingOperandsNumWords(spv::TensorAddressingOperandsMask mask) {
+  int result = 1;  // Count the mask
+  if ((mask & spv::TensorAddressingOperandsMask::TensorView) !=
+      spv::TensorAddressingOperandsMask::MaskNone)
+    ++result;
+  if ((mask & spv::TensorAddressingOperandsMask::DecodeFunc) !=
+      spv::TensorAddressingOperandsMask::MaskNone)
+    ++result;
+  return result;
+}
+
+spv_result_t ValidateCooperativeMatrixLoadStoreTensorNV(
+    ValidationState_t& _, const Instruction* inst) {
+  uint32_t type_id;
+  const char* opname;
+  if (inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV) {
+    type_id = inst->type_id();
+    opname = "spv::Op::OpCooperativeMatrixLoadTensorNV";
+  } else {
+    // get Object operand's type
+    type_id = _.FindDef(inst->GetOperandAs<uint32_t>(1))->type_id();
+    opname = "spv::Op::OpCooperativeMatrixStoreTensorNV";
+  }
+
+  auto matrix_type = _.FindDef(type_id);
+
+  if (matrix_type->opcode() != spv::Op::OpTypeCooperativeMatrixKHR) {
+    if (inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "spv::Op::OpCooperativeMatrixLoadTensorNV Result Type <id> "
+             << _.getIdName(type_id) << " is not a cooperative matrix type.";
+    } else {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "spv::Op::OpCooperativeMatrixStoreTensorNV Object type <id> "
+             << _.getIdName(type_id) << " is not a cooperative matrix type.";
+    }
+  }
+
+  const auto pointer_index =
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV) ? 2u : 0u;
+  const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index);
+  const auto pointer = _.FindDef(pointer_id);
+  if (!pointer ||
+      ((_.addressing_model() == spv::AddressingModel::Logical) &&
+       ((!_.features().variable_pointers &&
+         !spvOpcodeReturnsLogicalPointer(pointer->opcode())) ||
+        (_.features().variable_pointers &&
+         !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << opname << " Pointer <id> " << _.getIdName(pointer_id)
+           << " is not a logical pointer.";
+  }
+
+  const auto pointer_type_id = pointer->type_id();
+  const auto pointer_type = _.FindDef(pointer_type_id);
+  if (!pointer_type || pointer_type->opcode() != spv::Op::OpTypePointer) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << opname << " type for pointer <id> " << _.getIdName(pointer_id)
+           << " is not a pointer type.";
+  }
+
+  const auto storage_class_index = 1u;
+  const auto storage_class =
+      pointer_type->GetOperandAs<spv::StorageClass>(storage_class_index);
+
+  if (storage_class != spv::StorageClass::Workgroup &&
+      storage_class != spv::StorageClass::StorageBuffer &&
+      storage_class != spv::StorageClass::PhysicalStorageBuffer) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << _.VkErrorID(8973) << opname
+           << " storage class for pointer type <id> "
+           << _.getIdName(pointer_type_id)
+           << " is not Workgroup, StorageBuffer, or PhysicalStorageBuffer.";
+  }
+
+  if (inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV) {
+    const auto object_index = 3;
+    const auto object_id = inst->GetOperandAs<uint32_t>(object_index);
+    const auto object = _.FindDef(object_id);
+    if (!object || object->type_id() != type_id) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << opname << " Object <id> " << _.getIdName(object_id)
+             << " type does not match Result Type.";
+    }
+  }
+
+  const auto tensor_layout_index =
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV) ? 4u : 2u;
+  const auto tensor_layout_id =
+      inst->GetOperandAs<uint32_t>(tensor_layout_index);
+  const auto tensor_layout = _.FindDef(tensor_layout_id);
+  if (!tensor_layout || _.FindDef(tensor_layout->type_id())->opcode() !=
+                            spv::Op::OpTypeTensorLayoutNV) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << opname << " TensorLayout <id> " << _.getIdName(tensor_layout_id)
+           << " does not have a tensor layout type.";
+  }
+
+  const auto memory_access_index =
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadTensorNV) ? 5u : 3u;
+  if (inst->operands().size() > memory_access_index) {
+    if (auto error = CheckMemoryAccess(_, inst, memory_access_index))
+      return error;
+  }
+
+  const auto memory_access_mask =
+      inst->GetOperandAs<uint32_t>(memory_access_index);
+  const auto tensor_operands_index =
+      memory_access_index + MemoryAccessNumWords(memory_access_mask);
+  const auto tensor_operands =
+      inst->GetOperandAs<spv::TensorAddressingOperandsMask>(
+          tensor_operands_index);
+
+  if (inst->operands().size() <
+      tensor_operands_index +
+          TensorAddressingOperandsNumWords(tensor_operands)) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << opname << " not enough tensor addressing operands.";
+  }
+
+  uint32_t tensor_operand_index = tensor_operands_index + 1;
+  if ((tensor_operands & spv::TensorAddressingOperandsMask::TensorView) !=
+      spv::TensorAddressingOperandsMask::MaskNone) {
+    const auto tensor_view_id =
+        inst->GetOperandAs<uint32_t>(tensor_operand_index);
+    const auto tensor_view = _.FindDef(tensor_view_id);
+    if (!tensor_view || _.FindDef(tensor_view->type_id())->opcode() !=
+                            spv::Op::OpTypeTensorViewNV) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << opname << " TensorView <id> " << _.getIdName(tensor_view_id)
+             << " does not have a tensor view type.";
+    }
+
+    tensor_operand_index++;
+  }
+
+  if ((tensor_operands & spv::TensorAddressingOperandsMask::DecodeFunc) !=
+      spv::TensorAddressingOperandsMask::MaskNone) {
+    if (inst->opcode() == spv::Op::OpCooperativeMatrixStoreTensorNV) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "OpCooperativeMatrixStoreTensorNV does not support DecodeFunc.";
+    }
+    const auto decode_func_id =
+        inst->GetOperandAs<uint32_t>(tensor_operand_index);
+    const auto decode_func = _.FindDef(decode_func_id);
+
+    if (!decode_func || decode_func->opcode() != spv::Op::OpFunction) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << opname << " DecodeFunc <id> " << _.getIdName(decode_func_id)
+             << " is not a function.";
+    }
+
+    const auto component_type_index = 1;
+    const auto component_type_id =
+        matrix_type->GetOperandAs<uint32_t>(component_type_index);
+
+    const auto function_type =
+        _.FindDef(decode_func->GetOperandAs<uint32_t>(3));
+    if (function_type->GetOperandAs<uint32_t>(1) != component_type_id) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << opname << " DecodeFunc <id> " << _.getIdName(decode_func_id)
+             << " return type must match matrix component type.";
+    }
+
+    const auto decode_ptr_type_id = function_type->GetOperandAs<uint32_t>(2);
+    const auto decode_ptr_type = _.FindDef(decode_ptr_type_id);
+    auto decode_storage_class =
+        decode_ptr_type->GetOperandAs<spv::StorageClass>(storage_class_index);
+
+    if (decode_storage_class != spv::StorageClass::PhysicalStorageBuffer) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << opname << " DecodeFunc <id> " << _.getIdName(decode_func_id)
+             << " first parameter must be pointer to PhysicalStorageBuffer.";
+    }
+
+    const auto tensor_layout_type = _.FindDef(tensor_layout->type_id());
+
+    for (uint32_t param = 3; param < 5; ++param) {
+      const auto param_type_id = function_type->GetOperandAs<uint32_t>(param);
+      const auto param_type = _.FindDef(param_type_id);
+      if (param_type->opcode() != spv::Op::OpTypeArray) {
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
+               << opname << " DecodeFunc <id> " << _.getIdName(decode_func_id)
+               << " second/third parameter must be array of 32-bit integer "
+                  "with "
+               << " dimension equal to the tensor dimension.";
+      }
+      const auto length_index = 2u;
+      uint64_t array_length;
+      if (_.EvalConstantValUint64(
+              param_type->GetOperandAs<uint32_t>(length_index),
+              &array_length)) {
+        const auto tensor_layout_dim_id =
+            tensor_layout_type->GetOperandAs<uint32_t>(1);
+        uint64_t dim_value;
+        if (_.EvalConstantValUint64(tensor_layout_dim_id, &dim_value)) {
+          if (array_length != dim_value) {
+            return _.diag(SPV_ERROR_INVALID_ID, inst)
+                   << opname << " DecodeFunc <id> "
+                   << _.getIdName(decode_func_id)
+                   << " second/third parameter must be array of 32-bit integer "
+                      "with "
+                   << " dimension equal to the tensor dimension.";
+          }
+        }
+      }
+    }
+
+    tensor_operand_index++;
+  }
+
+  return SPV_SUCCESS;
+}
+
 spv_result_t ValidatePtrComparison(ValidationState_t& _,
                                    const Instruction* inst) {
   if (_.addressing_model() == spv::AddressingModel::Logical &&
@@ -2284,6 +2506,11 @@ spv_result_t MemoryPass(ValidationState_t& _, const Instruction* inst) {
       if (auto error = ValidateCooperativeMatrixLoadStoreKHR(_, inst))
         return error;
       break;
+    case spv::Op::OpCooperativeMatrixLoadTensorNV:
+    case spv::Op::OpCooperativeMatrixStoreTensorNV:
+      if (auto error = ValidateCooperativeMatrixLoadStoreTensorNV(_, inst))
+        return error;
+      break;
     case spv::Op::OpPtrEqual:
     case spv::Op::OpPtrNotEqual:
     case spv::Op::OpPtrDiff:

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

@@ -390,9 +390,8 @@ spv_result_t ValidateGroupNonUniformRotateKHR(ValidationState_t& _,
   if (inst->words().size() > 6) {
     const uint32_t cluster_size_op_id = inst->GetOperandAs<uint32_t>(5);
     const Instruction* cluster_size_inst = _.FindDef(cluster_size_op_id);
-    const uint32_t cluster_size_type =
-        cluster_size_inst ? cluster_size_inst->type_id() : 0;
-    if (!_.IsUnsignedIntScalarType(cluster_size_type)) {
+    if (!cluster_size_inst ||
+        !_.IsUnsignedIntScalarType(cluster_size_inst->type_id())) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "ClusterSize must be a scalar of integer type, whose "
                 "Signedness operand is 0.";

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

@@ -0,0 +1,184 @@
+// Copyright (c) 2024 NVIDIA Corporation
+//
+// 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.
+
+// Validate instructions that manipulate tensor layout and view objects
+
+#include "source/opcode.h"
+#include "source/spirv_target_env.h"
+#include "source/val/instruction.h"
+#include "source/val/validate.h"
+#include "source/val/validation_state.h"
+
+namespace spvtools {
+namespace val {
+namespace {
+
+spv_result_t ValidateTensorLayoutResultTypeNV(ValidationState_t& _,
+                                              const Instruction* inst) {
+  const auto result_type_index = 0;
+  const auto result_type_id = inst->GetOperandAs<uint32_t>(result_type_index);
+  const auto result_type = _.FindDef(result_type_id);
+
+  if (!result_type || spv::Op::OpTypeTensorLayoutNV != result_type->opcode()) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << spvOpcodeString(inst->opcode()) << " Result Type <id> "
+           << _.getIdName(result_type_id) << " is not a tensor layout type.";
+  }
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateTensorViewResultTypeNV(ValidationState_t& _,
+                                            const Instruction* inst) {
+  const auto result_type_index = 0;
+  const auto result_type_id = inst->GetOperandAs<uint32_t>(result_type_index);
+  const auto result_type = _.FindDef(result_type_id);
+
+  if (!result_type || spv::Op::OpTypeTensorViewNV != result_type->opcode()) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << spvOpcodeString(inst->opcode()) << " Result Type <id> "
+           << _.getIdName(result_type_id) << " is not a tensor view type.";
+  }
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateCreateTensorLayoutNV(ValidationState_t& _,
+                                          const Instruction* inst) {
+  if (auto error = ValidateTensorLayoutResultTypeNV(_, inst)) return error;
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateCreateTensorViewNV(ValidationState_t& _,
+                                        const Instruction* inst) {
+  if (auto error = ValidateTensorViewResultTypeNV(_, inst)) return error;
+
+  return SPV_SUCCESS;
+}
+
+enum ExpectedNumValues {
+  DIM,
+  DIMx2,
+  ONE,
+  FOUR,
+};
+
+spv_result_t ValidateTensorTypeWithDimValuesNV(ValidationState_t& _,
+                                               const Instruction* inst,
+                                               ExpectedNumValues expected,
+                                               bool is_view) {
+  std::string type_str;
+  if (is_view) {
+    if (auto error = ValidateTensorViewResultTypeNV(_, inst)) return error;
+    type_str = "TensorView";
+  } else {
+    if (auto error = ValidateTensorLayoutResultTypeNV(_, inst)) return error;
+    type_str = "TensorLayout";
+  }
+
+  const auto result_type_id = inst->GetOperandAs<uint32_t>(0);
+  const auto tensor_id = inst->GetOperandAs<uint32_t>(2);
+  const auto tensor = _.FindDef(tensor_id);
+  if (!tensor || result_type_id != tensor->type_id()) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << spvOpcodeString(inst->opcode()) << " Result Type <id> "
+           << _.getIdName(result_type_id) << " does not match " << type_str
+           << " type.";
+  }
+
+  const auto num_values = inst->operands().size() - 3;
+
+  const auto result_type = _.FindDef(result_type_id);
+  const auto dim_index = 1;
+  const auto dim_id = result_type->GetOperandAs<uint32_t>(dim_index);
+  uint64_t dim_value;
+  if (_.EvalConstantValUint64(dim_id, &dim_value)) {
+    uint64_t expected_num_values = 0;
+    switch (expected) {
+      case DIM:
+        expected_num_values = dim_value;
+        break;
+      case DIMx2:
+        expected_num_values = dim_value * 2;
+        break;
+      case ONE:
+        expected_num_values = 1;
+        break;
+      case FOUR:
+        expected_num_values = 4;
+        break;
+    }
+
+    if (num_values != expected_num_values) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << spvOpcodeString(inst->opcode())
+             << " unexpected number of operands.";
+    }
+  }
+
+  for (uint32_t i = 0; i < num_values; ++i) {
+    const auto val_id = inst->GetOperandAs<uint32_t>(i + 3);
+    const auto val = _.FindDef(val_id);
+    if (!val || !_.IsIntScalarType(val->type_id()) ||
+        _.GetBitWidth(val->type_id()) != 32) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << spvOpcodeString(inst->opcode()) << " operand <id> "
+             << _.getIdName(val_id) << " is not a 32-bit integer.";
+    }
+  }
+
+  return SPV_SUCCESS;
+}
+
+}  // namespace
+
+spv_result_t TensorLayoutPass(ValidationState_t& _, const Instruction* inst) {
+  switch (inst->opcode()) {
+    case spv::Op::OpCreateTensorLayoutNV:
+      if (auto error = ValidateCreateTensorLayoutNV(_, inst)) return error;
+      break;
+    case spv::Op::OpCreateTensorViewNV:
+      if (auto error = ValidateCreateTensorViewNV(_, inst)) return error;
+      break;
+    case spv::Op::OpTensorLayoutSetBlockSizeNV:
+    case spv::Op::OpTensorLayoutSetDimensionNV:
+    case spv::Op::OpTensorLayoutSetStrideNV:
+      if (auto error = ValidateTensorTypeWithDimValuesNV(_, inst, DIM, false))
+        return error;
+      break;
+    case spv::Op::OpTensorLayoutSliceNV:
+      if (auto error = ValidateTensorTypeWithDimValuesNV(_, inst, DIMx2, false))
+        return error;
+      break;
+    case spv::Op::OpTensorLayoutSetClampValueNV:
+      if (auto error = ValidateTensorTypeWithDimValuesNV(_, inst, ONE, false))
+        return error;
+      break;
+    case spv::Op::OpTensorViewSetDimensionNV:
+    case spv::Op::OpTensorViewSetStrideNV:
+      if (auto error = ValidateTensorTypeWithDimValuesNV(_, inst, DIM, true))
+        return error;
+      break;
+    case spv::Op::OpTensorViewSetClipNV:
+      if (auto error = ValidateTensorTypeWithDimValuesNV(_, inst, FOUR, true))
+        return error;
+      break;
+    default:
+      break;
+  }
+
+  return SPV_SUCCESS;
+}
+
+}  // namespace val
+}  // namespace spvtools

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

@@ -1,4 +1,5 @@
 // Copyright (c) 2018 Google LLC.
+// Copyright (c) 2024 NVIDIA Corporation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -582,6 +583,37 @@ spv_result_t ValidateTypeCooperativeMatrix(ValidationState_t& _,
     }
   }
 
+  uint64_t scope_value;
+  if (_.EvalConstantValUint64(scope_id, &scope_value)) {
+    if (scope_value == static_cast<uint32_t>(spv::Scope::Workgroup)) {
+      for (auto entry_point_id : _.entry_points()) {
+        if (!_.EntryPointHasLocalSizeOrId(entry_point_id)) {
+          return _.diag(SPV_ERROR_INVALID_ID, inst)
+                 << "OpTypeCooperativeMatrixKHR with ScopeWorkgroup "
+                 << "used without specifying LocalSize or LocalSizeId "
+                 << "for entry point <id> " << _.getIdName(entry_point_id);
+        }
+        const auto local_size = _.EntryPointLocalSizeOrId(entry_point_id);
+        const auto mode = local_size->GetOperandAs<spv::ExecutionMode>(1);
+        if (mode == spv::ExecutionMode::LocalSizeId) {
+          uint32_t local_size_ids[3] = {
+              local_size->GetOperandAs<uint32_t>(2),
+              local_size->GetOperandAs<uint32_t>(3),
+              local_size->GetOperandAs<uint32_t>(4),
+          };
+          for (auto id : local_size_ids) {
+            if (_.FindDef(id) > inst) {
+              return _.diag(SPV_ERROR_INVALID_ID, inst)
+                     << "OpTypeCooperativeMatrixKHR with ScopeWorkgroup "
+                     << "used before LocalSizeId constant value <id> "
+                     << _.getIdName(id) << " is defined.";
+            }
+          }
+        }
+      }
+    }
+  }
+
   return SPV_SUCCESS;
 }
 
@@ -611,6 +643,115 @@ spv_result_t ValidateTypeUntypedPointerKHR(ValidationState_t& _,
   }
   return SPV_SUCCESS;
 }
+
+spv_result_t ValidateTensorDim(ValidationState_t& _, const Instruction* inst) {
+  const auto dim_index = 1;
+  const auto dim_id = inst->GetOperandAs<uint32_t>(dim_index);
+  const auto dim = _.FindDef(dim_id);
+  if (!dim || !_.IsIntScalarType(dim->type_id()) ||
+      _.GetBitWidth(dim->type_id()) != 32) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << spvOpcodeString(inst->opcode()) << " Dim <id> "
+           << _.getIdName(dim_id) << " is not a 32-bit integer.";
+  }
+
+  constexpr uint32_t max_tensor_dim = 5;
+
+  uint64_t dim_value;
+  if (_.EvalConstantValUint64(dim_id, &dim_value)) {
+    if (dim_value == 0 || dim_value > max_tensor_dim) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << spvOpcodeString(inst->opcode()) << " Dim <id> "
+             << _.getIdName(dim_id) << " must be between 1 and "
+             << max_tensor_dim << ".";
+    }
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateTypeTensorLayoutNV(ValidationState_t& _,
+                                        const Instruction* inst) {
+  if (auto error = ValidateTensorDim(_, inst)) return error;
+
+  const auto clamp_index = 2;
+  const auto clamp_id = inst->GetOperandAs<uint32_t>(clamp_index);
+  const auto clamp = _.FindDef(clamp_id);
+  if (!clamp || !_.IsIntScalarType(clamp->type_id()) ||
+      _.GetBitWidth(clamp->type_id()) != 32) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << spvOpcodeString(inst->opcode()) << " ClampMode <id> "
+           << _.getIdName(clamp_id) << " is not a 32-bit integer.";
+  }
+
+  uint64_t clamp_value;
+  if (_.EvalConstantValUint64(clamp_id, &clamp_value)) {
+    if (clamp_value >
+        static_cast<uint32_t>(spv::TensorClampMode::RepeatMirrored)) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << spvOpcodeString(inst->opcode()) << " ClampMode <id> "
+             << _.getIdName(clamp_id) << " must be a valid TensorClampMode.";
+    }
+  }
+
+  return SPV_SUCCESS;
+}
+
+spv_result_t ValidateTypeTensorViewNV(ValidationState_t& _,
+                                      const Instruction* inst) {
+  if (auto error = ValidateTensorDim(_, inst)) return error;
+
+  const auto has_dim_index = 2;
+  const auto has_dim_id = inst->GetOperandAs<uint32_t>(has_dim_index);
+  const auto has_dim = _.FindDef(has_dim_id);
+  if (!has_dim || !_.IsBoolScalarType(has_dim->type_id())) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << spvOpcodeString(inst->opcode()) << " HasDimensions <id> "
+           << _.getIdName(has_dim_id) << " is not a boolean value.";
+  }
+
+  uint32_t permutation_mask = 0;
+  bool all_constant = true;
+  const auto num_dim = inst->operands().size() - 3;
+  for (size_t p_index = 3; p_index < inst->operands().size(); ++p_index) {
+    auto p_id = inst->GetOperandAs<uint32_t>(p_index);
+    const auto p = _.FindDef(p_id);
+    if (!p || !_.IsIntScalarType(p->type_id()) ||
+        _.GetBitWidth(p->type_id()) != 32) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << spvOpcodeString(inst->opcode()) << " Permutation <id> "
+             << _.getIdName(p_id) << " is not a 32-bit integer.";
+    }
+
+    uint64_t p_value;
+    if (_.EvalConstantValUint64(p_id, &p_value)) {
+      if (p_value >= num_dim) {
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
+               << spvOpcodeString(inst->opcode()) << " Permutation <id> "
+               << _.getIdName(p_id) << " must be a valid dimension.";
+      }
+      permutation_mask |= 1 << p_value;
+    } else {
+      all_constant = false;
+    }
+  }
+  if (all_constant && permutation_mask != (1U << num_dim) - 1U) {
+    return _.diag(SPV_ERROR_INVALID_ID, inst)
+           << spvOpcodeString(inst->opcode())
+           << " Permutation values don't form a valid permutation.";
+  }
+
+  uint64_t dim_value;
+  if (_.EvalConstantValUint64(inst->GetOperandAs<uint32_t>(1), &dim_value)) {
+    if (dim_value != num_dim) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << spvOpcodeString(inst->opcode())
+             << " Incorrect number of permutation values.";
+    }
+  }
+
+  return SPV_SUCCESS;
+}
 }  // namespace
 
 spv_result_t TypePass(ValidationState_t& _, const Instruction* inst) {
@@ -659,6 +800,12 @@ spv_result_t TypePass(ValidationState_t& _, const Instruction* inst) {
     case spv::Op::OpTypeUntypedPointerKHR:
       if (auto error = ValidateTypeUntypedPointerKHR(_, inst)) return error;
       break;
+    case spv::Op::OpTypeTensorLayoutNV:
+      if (auto error = ValidateTypeTensorLayoutNV(_, inst)) return error;
+      break;
+    case spv::Op::OpTypeTensorViewNV:
+      if (auto error = ValidateTypeTensorViewNV(_, inst)) return error;
+      break;
     default:
       break;
   }

+ 15 - 5
3rdparty/spirv-tools/source/val/validation_state.cpp

@@ -1290,8 +1290,9 @@ bool ValidationState_t::IsUnsigned64BitHandle(uint32_t id) const {
 }
 
 spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
-    const Instruction* inst, uint32_t m1, uint32_t m2) {
-  const auto m1_type = FindDef(m1);
+    const Instruction* inst, uint32_t result_type_id, uint32_t m2,
+    bool is_conversion, bool swap_row_col) {
+  const auto m1_type = FindDef(result_type_id);
   const auto m2_type = FindDef(m2);
 
   if (m1_type->opcode() != m2_type->opcode()) {
@@ -1307,6 +1308,10 @@ spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
   uint32_t m2_rows_id = m2_type->GetOperandAs<uint32_t>(3);
   uint32_t m2_cols_id = m2_type->GetOperandAs<uint32_t>(4);
 
+  if (swap_row_col) {
+    std::swap(m1_rows_id, m1_cols_id);
+  }
+
   bool m1_is_int32 = false, m1_is_const_int32 = false, m2_is_int32 = false,
        m2_is_const_int32 = false;
   uint32_t m1_value = 0, m2_value = 0;
@@ -1330,7 +1335,7 @@ spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
     return diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected rows of Matrix type and Result Type to be "
-           << "identical";
+           << (swap_row_col ? "swapped with columns" : "identical");
   }
 
   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
@@ -1341,7 +1346,7 @@ spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
     return diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected columns of Matrix type and Result Type to be "
-           << "identical";
+           << (swap_row_col ? "swapped with rows" : "identical");
   }
 
   if (m1_type->opcode() == spv::Op::OpTypeCooperativeMatrixKHR) {
@@ -1352,7 +1357,12 @@ spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
     std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
         EvalInt32IfConst(m2_use_id);
 
-    if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
+    if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value &&
+        // CooperativeMatrixConversionsNV allows conversions from Acc->A/B
+        !(is_conversion &&
+          HasCapability(spv::Capability::CooperativeMatrixConversionsNV) &&
+          m2_value ==
+              (uint32_t)spv::CooperativeMatrixUse::MatrixAccumulatorKHR)) {
       return diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Use of Matrix type and Result Type to be "
              << "identical";

+ 26 - 4
3rdparty/spirv-tools/source/val/validation_state.h

@@ -240,6 +240,21 @@ class ValidationState_t {
     entry_point_to_execution_modes_[entry_point].insert(execution_mode);
   }
 
+  /// Registers that the entry point declares its local size
+  void RegisterEntryPointLocalSize(uint32_t entry_point,
+                                   const Instruction* inst) {
+    entry_point_to_local_size_or_id_[entry_point] = inst;
+  }
+  /// Returns whether the entry point declares its local size
+  bool EntryPointHasLocalSizeOrId(uint32_t entry_point) const {
+    return entry_point_to_local_size_or_id_.find(entry_point) !=
+           entry_point_to_local_size_or_id_.end();
+  }
+  /// Returns the id of the local size
+  const Instruction* EntryPointLocalSizeOrId(uint32_t entry_point) const {
+    return entry_point_to_local_size_or_id_.find(entry_point)->second;
+  }
+
   /// Returns the interface descriptions of a given entry point.
   const std::vector<EntryPointDescription>& entry_point_descriptions(
       uint32_t entry_point) {
@@ -759,11 +774,14 @@ class ValidationState_t {
     return SpvDecorationString(uint32_t(decoration));
   }
 
-  // Returns whether type m1 and type m2 are cooperative matrices with
-  // the same "shape" (matching scope, rows, cols). If any are specialization
-  // constants, we assume they can match because we can't prove they don't.
+  // Returns whether type result_type_id and type m2 are cooperative matrices
+  // with the same "shape" (matching scope, rows, cols). If any are
+  // specialization constants, we assume they can match because we can't prove
+  // they don't.
   spv_result_t CooperativeMatrixShapesMatch(const Instruction* inst,
-                                            uint32_t m1, uint32_t m2);
+                                            uint32_t result_type_id,
+                                            uint32_t m2, bool is_conversion,
+                                            bool swap_row_col = false);
 
   // Returns true if |lhs| and |rhs| logically match and, if the decorations of
   // |rhs| are a subset of |lhs|.
@@ -949,6 +967,10 @@ class ValidationState_t {
   std::unordered_map<uint32_t, std::set<spv::ExecutionMode>>
       entry_point_to_execution_modes_;
 
+  // Mapping entry point -> local size execution mode instruction
+  std::unordered_map<uint32_t, const Instruction*>
+      entry_point_to_local_size_or_id_;
+
   /// Mapping function -> array of entry points inside this
   /// module which can (indirectly) call the function.
   std::unordered_map<uint32_t, std::vector<uint32_t>> function_to_entry_points_;

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