From b0ef2b8c4b75320c3e7cacb9781eed9883d83ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Sat, 28 Dec 2024 22:40:57 -0800 Subject: [PATCH] Updated spirv-tools. --- .../include/generated/build-version.inc | 2 +- .../include/generated/core.insts-unified1.inc | 23 ++ .../include/generated/enum_string_mapping.inc | 20 +- .../include/generated/extension_enum.inc | 2 + .../include/generated/generators.inc | 3 +- .../generated/operand.kinds-unified1.inc | 33 +++ .../include/spirv-tools/libspirv.h | 8 + 3rdparty/spirv-tools/source/binary.cpp | 5 +- 3rdparty/spirv-tools/source/disassemble.cpp | 2 + 3rdparty/spirv-tools/source/disassemble.h | 8 +- 3rdparty/spirv-tools/source/enum_set.h | 3 + 3rdparty/spirv-tools/source/ext_inst.cpp | 1 + 3rdparty/spirv-tools/source/opcode.cpp | 4 + 3rdparty/spirv-tools/source/operand.cpp | 19 ++ .../opt/aggressive_dead_code_elim_pass.cpp | 10 +- .../opt/eliminate_dead_members_pass.cpp | 15 ++ .../spirv-tools/source/opt/folding_rules.cpp | 1 + .../spirv-tools/source/opt/ir_context.cpp | 28 +- .../opt/local_access_chain_convert_pass.cpp | 3 +- .../opt/local_single_block_elim_pass.cpp | 3 +- .../opt/local_single_store_elim_pass.cpp | 3 +- .../spirv-tools/source/opt/loop_fission.cpp | 1 + 3rdparty/spirv-tools/source/opt/optimizer.cpp | 1 + .../source/opt/trim_capabilities_pass.cpp | 26 +- .../source/opt/trim_capabilities_pass.h | 1 + .../spirv-tools/source/opt/type_manager.cpp | 48 ++++ 3rdparty/spirv-tools/source/opt/types.cpp | 54 +++- 3rdparty/spirv-tools/source/opt/types.h | 53 ++++ 3rdparty/spirv-tools/source/print.cpp | 33 +-- .../spirv-tools/source/spirv_target_env.cpp | 134 +++++++--- .../spirv-tools/source/spirv_target_env.h | 7 + 3rdparty/spirv-tools/source/table.cpp | 1 + 3rdparty/spirv-tools/source/text.cpp | 6 +- 3rdparty/spirv-tools/source/val/function.h | 3 +- 3rdparty/spirv-tools/source/val/validate.cpp | 1 + 3rdparty/spirv-tools/source/val/validate.h | 3 + .../source/val/validate_arithmetics.cpp | 128 ++++++++- .../source/val/validate_conversion.cpp | 53 +++- .../source/val/validate_decorations.cpp | 2 +- .../source/val/validate_extensions.cpp | 124 +++++++-- .../source/val/validate_function.cpp | 85 +++++- .../spirv-tools/source/val/validate_id.cpp | 2 + .../spirv-tools/source/val/validate_image.cpp | 1 + .../source/val/validate_instruction.cpp | 6 + .../source/val/validate_layout.cpp | 4 +- .../source/val/validate_memory.cpp | 245 +++++++++++++++++- .../source/val/validate_non_uniform.cpp | 5 +- .../source/val/validate_tensor_layout.cpp | 184 +++++++++++++ .../spirv-tools/source/val/validate_type.cpp | 147 +++++++++++ .../source/val/validation_state.cpp | 20 +- .../spirv-tools/source/val/validation_state.h | 30 ++- 51 files changed, 1466 insertions(+), 138 deletions(-) create mode 100644 3rdparty/spirv-tools/source/val/validate_tensor_layout.cpp diff --git a/3rdparty/spirv-tools/include/generated/build-version.inc b/3rdparty/spirv-tools/include/generated/build-version.inc index 0bed940b045..5940312e135 100644 --- a/3rdparty/spirv-tools/include/generated/build-version.inc +++ b/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" diff --git a/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc b/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc index c5d3e804e4b..328e548dce0 100644 --- a/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc +++ b/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}, diff --git a/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc b/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc index 720f6a5e887..687a3c8a343 100644 --- a/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc +++ b/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc @@ -244,6 +244,8 @@ const char* ExtensionToString(Extension extension) { return "SPV_NV_compute_shader_derivatives"; case Extension::kSPV_NV_cooperative_matrix: return "SPV_NV_cooperative_matrix"; + case Extension::kSPV_NV_cooperative_matrix2: + return "SPV_NV_cooperative_matrix2"; case Extension::kSPV_NV_displacement_micromap: return "SPV_NV_displacement_micromap"; case Extension::kSPV_NV_fragment_shader_barycentric: @@ -274,6 +276,8 @@ const char* ExtensionToString(Extension extension) { return "SPV_NV_shading_rate"; case Extension::kSPV_NV_stereo_view_rendering: return "SPV_NV_stereo_view_rendering"; + case Extension::kSPV_NV_tensor_addressing: + return "SPV_NV_tensor_addressing"; case Extension::kSPV_NV_viewport_array2: return "SPV_NV_viewport_array2"; case Extension::kSPV_QCOM_image_processing: @@ -289,8 +293,8 @@ const char* ExtensionToString(Extension extension) { bool GetExtensionFromString(const char* str, Extension* extension) { - static const char* known_ext_strs[] = { "SPV_AMDX_shader_enqueue", "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_early_and_late_fragment_tests", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_ARM_cooperative_matrix_layouts", "SPV_ARM_core_builtins", "SPV_EXT_arithmetic_fence", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_mesh_shader", "SPV_EXT_opacity_micromap", "SPV_EXT_optnone", "SPV_EXT_physical_storage_buffer", "SPV_EXT_relaxed_printf_string_address_space", "SPV_EXT_replicated_composites", "SPV_EXT_shader_atomic_float16_add", "SPV_EXT_shader_atomic_float_add", "SPV_EXT_shader_atomic_float_min_max", "SPV_EXT_shader_image_int64", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_tile_image", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_arbitrary_precision_fixed_point", "SPV_INTEL_arbitrary_precision_floating_point", "SPV_INTEL_arbitrary_precision_integers", "SPV_INTEL_bfloat16_conversion", "SPV_INTEL_blocking_pipes", "SPV_INTEL_cache_controls", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fp_max_error", "SPV_INTEL_fpga_argument_interfaces", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "SPV_INTEL_fpga_dsp_control", "SPV_INTEL_fpga_invocation_pipelining_attributes", "SPV_INTEL_fpga_latency_control", "SPV_INTEL_fpga_loop_controls", "SPV_INTEL_fpga_memory_accesses", "SPV_INTEL_fpga_memory_attributes", "SPV_INTEL_fpga_reg", "SPV_INTEL_function_pointers", "SPV_INTEL_global_variable_fpga_decorations", "SPV_INTEL_global_variable_host_access", "SPV_INTEL_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_composites", "SPV_INTEL_loop_fuse", "SPV_INTEL_masked_gather_scatter", "SPV_INTEL_maximum_registers", "SPV_INTEL_media_block_io", "SPV_INTEL_memory_access_aliasing", "SPV_INTEL_optnone", "SPV_INTEL_runtime_aligned", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_split_barrier", "SPV_INTEL_subgroup_buffer_prefetch", "SPV_INTEL_subgroups", "SPV_INTEL_unstructured_loop_controls", "SPV_INTEL_usm_storage_classes", "SPV_INTEL_variable_length_array", "SPV_INTEL_vector_compute", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_bit_instructions", "SPV_KHR_compute_shader_derivatives", "SPV_KHR_cooperative_matrix", "SPV_KHR_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_float_controls2", "SPV_KHR_fragment_shader_barycentric", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "SPV_KHR_maximal_reconvergence", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_non_semantic_info", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_quad_control", "SPV_KHR_ray_cull_mask", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "SPV_KHR_ray_tracing_position_fetch", "SPV_KHR_relaxed_extended_instruction", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_rotate", "SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_vote", "SPV_KHR_terminate_invocation", "SPV_KHR_uniform_group_instructions", "SPV_KHR_untyped_pointers", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_KHR_workgroup_memory_explicit_layout", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_bindless_texture", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_displacement_micromap", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_raw_access_chains", "SPV_NV_ray_tracing", "SPV_NV_ray_tracing_motion_blur", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_atomic_fp16_vector", "SPV_NV_shader_image_footprint", "SPV_NV_shader_invocation_reorder", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_QCOM_image_processing", "SPV_QCOM_image_processing2", "SPV_VALIDATOR_ignore_type_decl_unique" }; - static const Extension known_ext_ids[] = { Extension::kSPV_AMDX_shader_enqueue, Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_early_and_late_fragment_tests, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_ARM_cooperative_matrix_layouts, Extension::kSPV_ARM_core_builtins, Extension::kSPV_EXT_arithmetic_fence, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_mesh_shader, Extension::kSPV_EXT_opacity_micromap, Extension::kSPV_EXT_optnone, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_relaxed_printf_string_address_space, Extension::kSPV_EXT_replicated_composites, Extension::kSPV_EXT_shader_atomic_float16_add, Extension::kSPV_EXT_shader_atomic_float_add, Extension::kSPV_EXT_shader_atomic_float_min_max, Extension::kSPV_EXT_shader_image_int64, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_tile_image, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_arbitrary_precision_fixed_point, Extension::kSPV_INTEL_arbitrary_precision_floating_point, Extension::kSPV_INTEL_arbitrary_precision_integers, Extension::kSPV_INTEL_bfloat16_conversion, Extension::kSPV_INTEL_blocking_pipes, Extension::kSPV_INTEL_cache_controls, Extension::kSPV_INTEL_debug_module, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_float_controls2, Extension::kSPV_INTEL_fp_fast_math_mode, Extension::kSPV_INTEL_fp_max_error, Extension::kSPV_INTEL_fpga_argument_interfaces, Extension::kSPV_INTEL_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, Extension::kSPV_INTEL_fpga_dsp_control, Extension::kSPV_INTEL_fpga_invocation_pipelining_attributes, Extension::kSPV_INTEL_fpga_latency_control, Extension::kSPV_INTEL_fpga_loop_controls, Extension::kSPV_INTEL_fpga_memory_accesses, Extension::kSPV_INTEL_fpga_memory_attributes, Extension::kSPV_INTEL_fpga_reg, Extension::kSPV_INTEL_function_pointers, Extension::kSPV_INTEL_global_variable_fpga_decorations, Extension::kSPV_INTEL_global_variable_host_access, Extension::kSPV_INTEL_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_composites, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_masked_gather_scatter, Extension::kSPV_INTEL_maximum_registers, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_memory_access_aliasing, Extension::kSPV_INTEL_optnone, Extension::kSPV_INTEL_runtime_aligned, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_split_barrier, Extension::kSPV_INTEL_subgroup_buffer_prefetch, Extension::kSPV_INTEL_subgroups, Extension::kSPV_INTEL_unstructured_loop_controls, Extension::kSPV_INTEL_usm_storage_classes, Extension::kSPV_INTEL_variable_length_array, Extension::kSPV_INTEL_vector_compute, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_bit_instructions, Extension::kSPV_KHR_compute_shader_derivatives, Extension::kSPV_KHR_cooperative_matrix, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_float_controls2, Extension::kSPV_KHR_fragment_shader_barycentric, Extension::kSPV_KHR_fragment_shading_rate, Extension::kSPV_KHR_integer_dot_product, Extension::kSPV_KHR_linkonce_odr, Extension::kSPV_KHR_maximal_reconvergence, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_non_semantic_info, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_quad_control, Extension::kSPV_KHR_ray_cull_mask, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, Extension::kSPV_KHR_ray_tracing_position_fetch, Extension::kSPV_KHR_relaxed_extended_instruction, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_rotate, Extension::kSPV_KHR_subgroup_uniform_control_flow, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_terminate_invocation, Extension::kSPV_KHR_uniform_group_instructions, Extension::kSPV_KHR_untyped_pointers, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_KHR_workgroup_memory_explicit_layout, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_bindless_texture, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_displacement_micromap, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_raw_access_chains, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_ray_tracing_motion_blur, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_atomic_fp16_vector, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_invocation_reorder, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_QCOM_image_processing, Extension::kSPV_QCOM_image_processing2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique }; + static const char* known_ext_strs[] = { "SPV_AMDX_shader_enqueue", "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_early_and_late_fragment_tests", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_ARM_cooperative_matrix_layouts", "SPV_ARM_core_builtins", "SPV_EXT_arithmetic_fence", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_mesh_shader", "SPV_EXT_opacity_micromap", "SPV_EXT_optnone", "SPV_EXT_physical_storage_buffer", "SPV_EXT_relaxed_printf_string_address_space", "SPV_EXT_replicated_composites", "SPV_EXT_shader_atomic_float16_add", "SPV_EXT_shader_atomic_float_add", "SPV_EXT_shader_atomic_float_min_max", "SPV_EXT_shader_image_int64", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_tile_image", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_arbitrary_precision_fixed_point", "SPV_INTEL_arbitrary_precision_floating_point", "SPV_INTEL_arbitrary_precision_integers", "SPV_INTEL_bfloat16_conversion", "SPV_INTEL_blocking_pipes", "SPV_INTEL_cache_controls", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fp_max_error", "SPV_INTEL_fpga_argument_interfaces", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "SPV_INTEL_fpga_dsp_control", "SPV_INTEL_fpga_invocation_pipelining_attributes", "SPV_INTEL_fpga_latency_control", "SPV_INTEL_fpga_loop_controls", "SPV_INTEL_fpga_memory_accesses", "SPV_INTEL_fpga_memory_attributes", "SPV_INTEL_fpga_reg", "SPV_INTEL_function_pointers", "SPV_INTEL_global_variable_fpga_decorations", "SPV_INTEL_global_variable_host_access", "SPV_INTEL_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_composites", "SPV_INTEL_loop_fuse", "SPV_INTEL_masked_gather_scatter", "SPV_INTEL_maximum_registers", "SPV_INTEL_media_block_io", "SPV_INTEL_memory_access_aliasing", "SPV_INTEL_optnone", "SPV_INTEL_runtime_aligned", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_split_barrier", "SPV_INTEL_subgroup_buffer_prefetch", "SPV_INTEL_subgroups", "SPV_INTEL_unstructured_loop_controls", "SPV_INTEL_usm_storage_classes", "SPV_INTEL_variable_length_array", "SPV_INTEL_vector_compute", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_bit_instructions", "SPV_KHR_compute_shader_derivatives", "SPV_KHR_cooperative_matrix", "SPV_KHR_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_float_controls2", "SPV_KHR_fragment_shader_barycentric", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "SPV_KHR_maximal_reconvergence", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_non_semantic_info", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_quad_control", "SPV_KHR_ray_cull_mask", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "SPV_KHR_ray_tracing_position_fetch", "SPV_KHR_relaxed_extended_instruction", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_rotate", "SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_vote", "SPV_KHR_terminate_invocation", "SPV_KHR_uniform_group_instructions", "SPV_KHR_untyped_pointers", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_KHR_workgroup_memory_explicit_layout", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_bindless_texture", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_cooperative_matrix2", "SPV_NV_displacement_micromap", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_raw_access_chains", "SPV_NV_ray_tracing", "SPV_NV_ray_tracing_motion_blur", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_atomic_fp16_vector", "SPV_NV_shader_image_footprint", "SPV_NV_shader_invocation_reorder", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_tensor_addressing", "SPV_NV_viewport_array2", "SPV_QCOM_image_processing", "SPV_QCOM_image_processing2", "SPV_VALIDATOR_ignore_type_decl_unique" }; + static const Extension known_ext_ids[] = { Extension::kSPV_AMDX_shader_enqueue, Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_early_and_late_fragment_tests, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_ARM_cooperative_matrix_layouts, Extension::kSPV_ARM_core_builtins, Extension::kSPV_EXT_arithmetic_fence, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_mesh_shader, Extension::kSPV_EXT_opacity_micromap, Extension::kSPV_EXT_optnone, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_relaxed_printf_string_address_space, Extension::kSPV_EXT_replicated_composites, Extension::kSPV_EXT_shader_atomic_float16_add, Extension::kSPV_EXT_shader_atomic_float_add, Extension::kSPV_EXT_shader_atomic_float_min_max, Extension::kSPV_EXT_shader_image_int64, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_tile_image, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_arbitrary_precision_fixed_point, Extension::kSPV_INTEL_arbitrary_precision_floating_point, Extension::kSPV_INTEL_arbitrary_precision_integers, Extension::kSPV_INTEL_bfloat16_conversion, Extension::kSPV_INTEL_blocking_pipes, Extension::kSPV_INTEL_cache_controls, Extension::kSPV_INTEL_debug_module, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_float_controls2, Extension::kSPV_INTEL_fp_fast_math_mode, Extension::kSPV_INTEL_fp_max_error, Extension::kSPV_INTEL_fpga_argument_interfaces, Extension::kSPV_INTEL_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, Extension::kSPV_INTEL_fpga_dsp_control, Extension::kSPV_INTEL_fpga_invocation_pipelining_attributes, Extension::kSPV_INTEL_fpga_latency_control, Extension::kSPV_INTEL_fpga_loop_controls, Extension::kSPV_INTEL_fpga_memory_accesses, Extension::kSPV_INTEL_fpga_memory_attributes, Extension::kSPV_INTEL_fpga_reg, Extension::kSPV_INTEL_function_pointers, Extension::kSPV_INTEL_global_variable_fpga_decorations, Extension::kSPV_INTEL_global_variable_host_access, Extension::kSPV_INTEL_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_composites, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_masked_gather_scatter, Extension::kSPV_INTEL_maximum_registers, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_memory_access_aliasing, Extension::kSPV_INTEL_optnone, Extension::kSPV_INTEL_runtime_aligned, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_split_barrier, Extension::kSPV_INTEL_subgroup_buffer_prefetch, Extension::kSPV_INTEL_subgroups, Extension::kSPV_INTEL_unstructured_loop_controls, Extension::kSPV_INTEL_usm_storage_classes, Extension::kSPV_INTEL_variable_length_array, Extension::kSPV_INTEL_vector_compute, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_bit_instructions, Extension::kSPV_KHR_compute_shader_derivatives, Extension::kSPV_KHR_cooperative_matrix, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_float_controls2, Extension::kSPV_KHR_fragment_shader_barycentric, Extension::kSPV_KHR_fragment_shading_rate, Extension::kSPV_KHR_integer_dot_product, Extension::kSPV_KHR_linkonce_odr, Extension::kSPV_KHR_maximal_reconvergence, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_non_semantic_info, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_quad_control, Extension::kSPV_KHR_ray_cull_mask, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, Extension::kSPV_KHR_ray_tracing_position_fetch, Extension::kSPV_KHR_relaxed_extended_instruction, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_rotate, Extension::kSPV_KHR_subgroup_uniform_control_flow, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_terminate_invocation, Extension::kSPV_KHR_uniform_group_instructions, Extension::kSPV_KHR_untyped_pointers, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_KHR_workgroup_memory_explicit_layout, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_bindless_texture, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_cooperative_matrix2, Extension::kSPV_NV_displacement_micromap, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_raw_access_chains, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_ray_tracing_motion_blur, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_atomic_fp16_vector, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_invocation_reorder, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_tensor_addressing, Extension::kSPV_NV_viewport_array2, Extension::kSPV_QCOM_image_processing, Extension::kSPV_QCOM_image_processing2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique }; const auto b = std::begin(known_ext_strs); const auto e = std::end(known_ext_strs); const auto found = std::equal_range( @@ -638,6 +642,18 @@ const char* CapabilityToString(spv::Capability capability) { return "RayTracingDisplacementMicromapNV"; case spv::Capability::RawAccessChainsNV: return "RawAccessChainsNV"; + case spv::Capability::CooperativeMatrixReductionsNV: + return "CooperativeMatrixReductionsNV"; + case spv::Capability::CooperativeMatrixConversionsNV: + return "CooperativeMatrixConversionsNV"; + case spv::Capability::CooperativeMatrixPerElementOperationsNV: + return "CooperativeMatrixPerElementOperationsNV"; + case spv::Capability::CooperativeMatrixTensorAddressingNV: + return "CooperativeMatrixTensorAddressingNV"; + case spv::Capability::CooperativeMatrixBlockLoadsNV: + return "CooperativeMatrixBlockLoadsNV"; + case spv::Capability::TensorAddressingNV: + return "TensorAddressingNV"; case spv::Capability::SubgroupShuffleINTEL: return "SubgroupShuffleINTEL"; case spv::Capability::SubgroupBufferBlockIOINTEL: diff --git a/3rdparty/spirv-tools/include/generated/extension_enum.inc b/3rdparty/spirv-tools/include/generated/extension_enum.inc index 8b597e05324..37aa8fef17c 100644 --- a/3rdparty/spirv-tools/include/generated/extension_enum.inc +++ b/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, diff --git a/3rdparty/spirv-tools/include/generated/generators.inc b/3rdparty/spirv-tools/include/generated/generators.inc index 993e7152a8e..35973e1336f 100644 --- a/3rdparty/spirv-tools/include/generated/generators.inc +++ b/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"}, \ No newline at end of file +{45, "Kitsunebi Games", "Nuvk SPIR-V Emitter and DLSL compiler", "Kitsunebi Games Nuvk SPIR-V Emitter and DLSL compiler"}, +{46, "Nintendo", "", "Nintendo"}, \ No newline at end of file diff --git a/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc b/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc index 7a7490c5e1e..a80b82d73a6 100644 --- a/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc +++ b/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}, diff --git a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h index 0624e023603..88bc785d06a 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h +++ b/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; diff --git a/3rdparty/spirv-tools/source/binary.cpp b/3rdparty/spirv-tools/source/binary.cpp index 772e98c0a2f..ed574985760 100644 --- a/3rdparty/spirv-tools/source/binary.cpp +++ b/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. diff --git a/3rdparty/spirv-tools/source/disassemble.cpp b/3rdparty/spirv-tools/source/disassemble.cpp index db99151a901..93791a0ca79 100644 --- a/3rdparty/spirv-tools/source/disassemble.cpp +++ b/3rdparty/spirv-tools/source/disassemble.cpp @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include #include #include diff --git a/3rdparty/spirv-tools/source/disassemble.h b/3rdparty/spirv-tools/source/disassemble.h index 9baeaa43e0f..b6d13c647bf 100644 --- a/3rdparty/spirv-tools/source/disassemble.h +++ b/3rdparty/spirv-tools/source/disassemble.h @@ -15,7 +15,7 @@ #ifndef SOURCE_DISASSEMBLE_H_ #define SOURCE_DISASSEMBLE_H_ -#include +#include #include #include @@ -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_|. diff --git a/3rdparty/spirv-tools/source/enum_set.h b/3rdparty/spirv-tools/source/enum_set.h index a3751388abd..340f5b97860 100644 --- a/3rdparty/spirv-tools/source/enum_set.h +++ b/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 + #include #include #include #include #include +#include #include #include #include diff --git a/3rdparty/spirv-tools/source/ext_inst.cpp b/3rdparty/spirv-tools/source/ext_inst.cpp index 9a5ba84e466..f2ff63fc202 100644 --- a/3rdparty/spirv-tools/source/ext_inst.cpp +++ b/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: diff --git a/3rdparty/spirv-tools/source/opcode.cpp b/3rdparty/spirv-tools/source/opcode.cpp index ea03bd67117..f4fd3eec421 100644 --- a/3rdparty/spirv-tools/source/opcode.cpp +++ b/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; diff --git a/3rdparty/spirv-tools/source/operand.cpp b/3rdparty/spirv-tools/source/operand.cpp index 9bee647fca3..548564662e7 100644 --- a/3rdparty/spirv-tools/source/operand.cpp +++ b/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 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; diff --git a/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp index 79654224ac0..333ef7bdca9 100644 --- a/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp +++ b/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 } diff --git a/3rdparty/spirv-tools/source/opt/eliminate_dead_members_pass.cpp b/3rdparty/spirv-tools/source/opt/eliminate_dead_members_pass.cpp index 1c98502e223..e440296ffd5 100644 --- a/3rdparty/spirv-tools/source/opt/eliminate_dead_members_pass.cpp +++ b/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: diff --git a/3rdparty/spirv-tools/source/opt/folding_rules.cpp b/3rdparty/spirv-tools/source/opt/folding_rules.cpp index b1152f473b6..5748f971889 100644 --- a/3rdparty/spirv-tools/source/opt/folding_rules.cpp +++ b/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. diff --git a/3rdparty/spirv-tools/source/opt/ir_context.cpp b/3rdparty/spirv-tools/source/opt/ir_context.cpp index d864b7c02ee..1cf0d74bf58 100644 --- a/3rdparty/spirv-tools/source/opt/ir_context.cpp +++ b/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* 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) { diff --git a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp b/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp index ad0277474ef..91ea7c69add 100644 --- a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp +++ b/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( diff --git a/3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp index 7df17d5d623..f9c5a79769b 100644 --- a/3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp +++ b/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 diff --git a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp index bb7bba87ebe..38fa14ef46b 100644 --- a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp +++ b/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 users; diff --git a/3rdparty/spirv-tools/source/opt/loop_fission.cpp b/3rdparty/spirv-tools/source/opt/loop_fission.cpp index 2ae05c3c3f3..1bbe4baa34e 100644 --- a/3rdparty/spirv-tools/source/opt/loop_fission.cpp +++ b/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; } diff --git a/3rdparty/spirv-tools/source/opt/optimizer.cpp b/3rdparty/spirv-tools/source/opt/optimizer.cpp index 94b15c6ab55..a41885c0e61 100644 --- a/3rdparty/spirv-tools/source/opt/optimizer.cpp +++ b/3rdparty/spirv-tools/source/opt/optimizer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/3rdparty/spirv-tools/source/opt/trim_capabilities_pass.cpp b/3rdparty/spirv-tools/source/opt/trim_capabilities_pass.cpp index 8a8535143d1..34fbc4496b8 100644 --- a/3rdparty/spirv-tools/source/opt/trim_capabilities_pass.cpp +++ b/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 +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 Handler_OpImageSparseRead_StorageImageReadWithoutFormat( const Instruction* instruction) { @@ -365,9 +388,10 @@ Handler_OpImageSparseRead_StorageImageReadWithoutFormat( } // Opcode of interest to determine capabilities requirements. -constexpr std::array, 12> kOpcodeHandlers{{ +constexpr std::array, 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 }, diff --git a/3rdparty/spirv-tools/source/opt/trim_capabilities_pass.h b/3rdparty/spirv-tools/source/opt/trim_capabilities_pass.h index 91d32a563b5..1d1183ab23a 100644 --- a/3rdparty/spirv-tools/source/opt/trim_capabilities_pass.h +++ b/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, diff --git a/3rdparty/spirv-tools/source/opt/type_manager.cpp b/3rdparty/spirv-tools/source/opt/type_manager.cpp index 79648ad4974..88106b60876 100644 --- a/3rdparty/spirv-tools/source/opt/type_manager.cpp +++ b/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( + context(), spv::Op::OpTypeTensorLayoutNV, 0, id, + std::initializer_list{ + {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 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(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(tl_type->dim_id(), + tl_type->clamp_mode_id()); + break; + } + case Type::kTensorViewNV: { + const TensorViewNV* tv_type = type.AsTensorViewNV(); + rebuilt_ty = MakeUnique( + 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 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; diff --git a/3rdparty/spirv-tools/source/opt/types.cpp b/3rdparty/spirv-tools/source/opt/types.cpp index b18b8cb1ae6..8ccf6c9a2f0 100644 --- a/3rdparty/spirv-tools/source/opt/types.cpp +++ b/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& 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 diff --git a/3rdparty/spirv-tools/source/opt/types.h b/3rdparty/spirv-tools/source/opt/types.h index 16a948cec55..6092c3c92ca 100644 --- a/3rdparty/spirv-tools/source/opt/types.h +++ b/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() methods, // which is used as a way to probe the actual . @@ -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& 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& 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 perm_; +}; + #define DefineParameterlessType(type, name) \ class type : public Type { \ public: \ diff --git a/3rdparty/spirv-tools/source/print.cpp b/3rdparty/spirv-tools/source/print.cpp index f36812ef56e..3143db17811 100644 --- a/3rdparty/spirv-tools/source/print.cpp +++ b/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 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 diff --git a/3rdparty/spirv-tools/source/spirv_target_env.cpp b/3rdparty/spirv-tools/source/spirv_target_env.cpp index 585f8b65a25..d1172a060ab 100644 --- a/3rdparty/spirv-tools/source/spirv_target_env.cpp +++ b/3rdparty/spirv-tools/source/spirv_target_env.cpp @@ -14,11 +14,13 @@ #include "source/spirv_target_env.h" +#include #include +#include #include #include -#include +#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 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_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 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& 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(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: diff --git a/3rdparty/spirv-tools/source/spirv_target_env.h b/3rdparty/spirv-tools/source/spirv_target_env.h index f3b0c2f6f2a..4378f06fa4a 100644 --- a/3rdparty/spirv-tools/source/spirv_target_env.h +++ b/3rdparty/spirv-tools/source/spirv_target_env.h @@ -16,6 +16,8 @@ #define SOURCE_SPIRV_TARGET_ENV_H_ #include +#include +#include #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& text, + spv_target_env* env); + #endif // SOURCE_SPIRV_TARGET_ENV_H_ diff --git a/3rdparty/spirv-tools/source/table.cpp b/3rdparty/spirv-tools/source/table.cpp index 822cefebd7b..01df1bc0d83 100644 --- a/3rdparty/spirv-tools/source/table.cpp +++ b/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; diff --git a/3rdparty/spirv-tools/source/text.cpp b/3rdparty/spirv-tools/source/text.cpp index fda46ec2ef3..2154e8552e0 100644 --- a/3rdparty/spirv-tools/source/text.cpp +++ b/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) diff --git a/3rdparty/spirv-tools/source/val/function.h b/3rdparty/spirv-tools/source/val/function.h index 481179442e3..d3dd63966d8 100644 --- a/3rdparty/spirv-tools/source/val/function.h +++ b/3rdparty/spirv-tools/source/val/function.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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 diff --git a/3rdparty/spirv-tools/source/val/validate.cpp b/3rdparty/spirv-tools/source/val/validate.cpp index 32368075c57..2d10347d80f 100644 --- a/3rdparty/spirv-tools/source/val/validate.cpp +++ b/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. diff --git a/3rdparty/spirv-tools/source/val/validate.h b/3rdparty/spirv-tools/source/val/validate.h index 78093ce5fde..5514ff738e2 100644 --- a/3rdparty/spirv-tools/source/val/validate.h +++ b/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. diff --git a/3rdparty/spirv-tools/source/val/validate_arithmetics.cpp b/3rdparty/spirv-tools/source/val/validate_arithmetics.cpp index b608a859529..8b0049c5b46 100644 --- a/3rdparty/spirv-tools/source/val/validate_arithmetics.cpp +++ b/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(1); + + const auto matrix_id = inst->GetOperandAs(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(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(2) != + matrix_type->GetOperandAs(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(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 result_rows, result_cols, matrix_rows, + matrix_cols; + result_rows = + _.EvalInt32IfConst(_.FindDef(result_type)->GetOperandAs(3)); + result_cols = + _.EvalInt32IfConst(_.FindDef(result_type)->GetOperandAs(4)); + matrix_rows = _.EvalInt32IfConst(matrix_type->GetOperandAs(3)); + matrix_cols = _.EvalInt32IfConst(matrix_type->GetOperandAs(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(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(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(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; } diff --git a/3rdparty/spirv-tools/source/val/validate_conversion.cpp b/3rdparty/spirv-tools/source/val/validate_conversion.cpp index b2892a8630b..770b8e2e33b 100644 --- a/3rdparty/spirv-tools/source/val/validate_conversion.cpp +++ b/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(1) != + _.FindDef(input_type)->GetOperandAs(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; } diff --git a/3rdparty/spirv-tools/source/val/validate_decorations.cpp b/3rdparty/spirv-tools/source/val/validate_decorations.cpp index 7f374bbd271..e680bd6eb99 100644 --- a/3rdparty/spirv-tools/source/val/validate_decorations.cpp +++ b/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: diff --git a/3rdparty/spirv-tools/source/val/validate_extensions.cpp b/3rdparty/spirv-tools/source/val/validate_extensions.cpp index 74974a4fef0..c2d8d593586 100644 --- a/3rdparty/spirv-tools/source/val/validate_extensions.cpp +++ b/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: { diff --git a/3rdparty/spirv-tools/source/val/validate_function.cpp b/3rdparty/spirv-tools/source/val/validate_function.cpp index 26b36682826..624b4e244b7 100644 --- a/3rdparty/spirv-tools/source/val/validate_function.cpp +++ b/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(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 " << _.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(3); + const auto function = _.FindDef(function_id); + if (!function || spv::Op::OpFunction != function->opcode()) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpCooperativeMatrixPerElementOpNV Function " + << _.getIdName(function_id) << " is not a function."; + } + + const auto matrix_id = inst->GetOperandAs(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 " + << _.getIdName(matrix_id) << " is not a cooperative matrix."; + } + + const auto result_type_id = inst->GetOperandAs(0); + if (matrix_type_id != result_type_id) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpCooperativeMatrixPerElementOpNV Result Type " + << _.getIdName(result_type_id) << " must match matrix type " + << _.getIdName(matrix_type_id) << "."; + } + + const auto matrix_comp_type_id = + _.FindDef(matrix_type_id)->GetOperandAs(1); + const auto function_type_id = function->GetOperandAs(3); + const auto function_type = _.FindDef(function_type_id); + auto return_type_id = function_type->GetOperandAs(1); + if (return_type_id != matrix_comp_type_id) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpCooperativeMatrixPerElementOpNV function return type " + << _.getIdName(return_type_id) + << " must match matrix component type " + << _.getIdName(matrix_comp_type_id) << "."; + } + + if (function_type->operands().size() < 5) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpCooperativeMatrixPerElementOpNV function type " + << _.getIdName(function_type_id) + << " must have a least three parameters."; + } + + const auto param0_id = function_type->GetOperandAs(2); + const auto param1_id = function_type->GetOperandAs(3); + const auto param2_id = function_type->GetOperandAs(4); + if (!_.IsIntScalarType(param0_id) || _.GetBitWidth(param0_id) != 32) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpCooperativeMatrixPerElementOpNV function type first parameter " + "type " + << _.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 " + << _.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 " + << _.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; } diff --git a/3rdparty/spirv-tools/source/val/validate_id.cpp b/3rdparty/spirv-tools/source/val/validate_id.cpp index 0d1e84123e5..00be150cb53 100644 --- a/3rdparty/spirv-tools/source/val/validate_id.cpp +++ b/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) && diff --git a/3rdparty/spirv-tools/source/val/validate_image.cpp b/3rdparty/spirv-tools/source/val/validate_image.cpp index 04100dd7112..cb987d8242d 100644 --- a/3rdparty/spirv-tools/source/val/validate_image.cpp +++ b/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; diff --git a/3rdparty/spirv-tools/source/val/validate_instruction.cpp b/3rdparty/spirv-tools/source/val/validate_instruction.cpp index 5bc4d2cef4c..39b1c021679 100644 --- a/3rdparty/spirv-tools/source/val/validate_instruction.cpp +++ b/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(1) == + spv::ExecutionMode::LocalSize || + inst->GetOperandAs(1) == + spv::ExecutionMode::LocalSizeId) { + _.RegisterEntryPointLocalSize(entry_point, inst); + } } else if (opcode == spv::Op::OpVariable) { const auto storage_class = inst->GetOperandAs(2); if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) { diff --git a/3rdparty/spirv-tools/source/val/validate_layout.cpp b/3rdparty/spirv-tools/source/val/validate_layout.cpp index 05a8675101e..baf36b89bd5 100644 --- a/3rdparty/spirv-tools/source/val/validate_layout.cpp +++ b/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 " diff --git a/3rdparty/spirv-tools/source/val/validate_memory.cpp b/3rdparty/spirv-tools/source/val/validate_memory.cpp index 830c3ea1197..32f642712c5 100644 --- a/3rdparty/spirv-tools/source/val/validate_memory.cpp +++ b/3rdparty/spirv-tools/source/val/validate_memory.cpp @@ -233,6 +233,7 @@ std::pair 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(2)); @@ -241,6 +242,7 @@ std::pair GetStorageClass( break; } case spv::Op::OpCooperativeMatrixStoreNV: + case spv::Op::OpCooperativeMatrixStoreTensorNV: case spv::Op::OpCooperativeMatrixStoreKHR: case spv::Op::OpStore: { auto store_pointer = _.FindDef(inst->GetOperandAs(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(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 " - << _.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 " + << _.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(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 " + << _.getIdName(type_id) << " is not a cooperative matrix type."; + } else { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "spv::Op::OpCooperativeMatrixStoreTensorNV Object type " + << _.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(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 " << _.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 " << _.getIdName(pointer_id) + << " is not a pointer type."; + } + + const auto storage_class_index = 1u; + const auto storage_class = + pointer_type->GetOperandAs(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 " + << _.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(object_index); + const auto object = _.FindDef(object_id); + if (!object || object->type_id() != type_id) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << opname << " Object " << _.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(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 " << _.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(memory_access_index); + const auto tensor_operands_index = + memory_access_index + MemoryAccessNumWords(memory_access_mask); + const auto tensor_operands = + inst->GetOperandAs( + 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(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 " << _.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(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 " << _.getIdName(decode_func_id) + << " is not a function."; + } + + const auto component_type_index = 1; + const auto component_type_id = + matrix_type->GetOperandAs(component_type_index); + + const auto function_type = + _.FindDef(decode_func->GetOperandAs(3)); + if (function_type->GetOperandAs(1) != component_type_id) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << opname << " DecodeFunc " << _.getIdName(decode_func_id) + << " return type must match matrix component type."; + } + + const auto decode_ptr_type_id = function_type->GetOperandAs(2); + const auto decode_ptr_type = _.FindDef(decode_ptr_type_id); + auto decode_storage_class = + decode_ptr_type->GetOperandAs(storage_class_index); + + if (decode_storage_class != spv::StorageClass::PhysicalStorageBuffer) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << opname << " DecodeFunc " << _.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(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 " << _.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(length_index), + &array_length)) { + const auto tensor_layout_dim_id = + tensor_layout_type->GetOperandAs(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 " + << _.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: diff --git a/3rdparty/spirv-tools/source/val/validate_non_uniform.cpp b/3rdparty/spirv-tools/source/val/validate_non_uniform.cpp index 75967d2ff98..fd422a50ed4 100644 --- a/3rdparty/spirv-tools/source/val/validate_non_uniform.cpp +++ b/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(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."; diff --git a/3rdparty/spirv-tools/source/val/validate_tensor_layout.cpp b/3rdparty/spirv-tools/source/val/validate_tensor_layout.cpp new file mode 100644 index 00000000000..35c766b83d6 --- /dev/null +++ b/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(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 " + << _.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(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 " + << _.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(0); + const auto tensor_id = inst->GetOperandAs(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 " + << _.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(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(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 " + << _.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 diff --git a/3rdparty/spirv-tools/source/val/validate_type.cpp b/3rdparty/spirv-tools/source/val/validate_type.cpp index 32024b7356b..5101a40c452 100644 --- a/3rdparty/spirv-tools/source/val/validate_type.cpp +++ b/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(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 " << _.getIdName(entry_point_id); + } + const auto local_size = _.EntryPointLocalSizeOrId(entry_point_id); + const auto mode = local_size->GetOperandAs(1); + if (mode == spv::ExecutionMode::LocalSizeId) { + uint32_t local_size_ids[3] = { + local_size->GetOperandAs(2), + local_size->GetOperandAs(3), + local_size->GetOperandAs(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 " + << _.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(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 " + << _.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 " + << _.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(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 " + << _.getIdName(clamp_id) << " is not a 32-bit integer."; + } + + uint64_t clamp_value; + if (_.EvalConstantValUint64(clamp_id, &clamp_value)) { + if (clamp_value > + static_cast(spv::TensorClampMode::RepeatMirrored)) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << spvOpcodeString(inst->opcode()) << " ClampMode " + << _.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(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 " + << _.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(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 " + << _.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 " + << _.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(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; } diff --git a/3rdparty/spirv-tools/source/val/validation_state.cpp b/3rdparty/spirv-tools/source/val/validation_state.cpp index 2afcacc3379..da9174fa5ca 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.cpp +++ b/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(3); uint32_t m2_cols_id = m2_type->GetOperandAs(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"; diff --git a/3rdparty/spirv-tools/source/val/validation_state.h b/3rdparty/spirv-tools/source/val/validation_state.h index 372b5b7b9f3..44551add35e 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.h +++ b/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& 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> entry_point_to_execution_modes_; + // Mapping entry point -> local size execution mode instruction + std::unordered_map + 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> function_to_entry_points_;