diff --git a/3rdparty/spirv-tools/include/generated/build-version.inc b/3rdparty/spirv-tools/include/generated/build-version.inc index fa7de6865..fec6cef28 100644 --- a/3rdparty/spirv-tools/include/generated/build-version.inc +++ b/3rdparty/spirv-tools/include/generated/build-version.inc @@ -1 +1 @@ -"v2022.3-dev", "SPIRV-Tools v2022.3-dev ea8f609ef63df14ebdb0f43ba5437717fc8fd494" +"v2022.4-dev", "SPIRV-Tools v2022.4-dev 9af8fde5414723dfc630c20d733548f881e4804a" diff --git a/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc b/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc index d3a781e71..88d806909 100644 --- a/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc +++ b/3rdparty/spirv-tools/include/generated/core.insts-unified1.inc @@ -43,6 +43,7 @@ static const SpvCapability pygen_variable_caps_LiteralSampler[] = {SpvCapability static const SpvCapability pygen_variable_caps_LongConstantCompositeINTEL[] = {SpvCapabilityLongConstantCompositeINTEL}; static const SpvCapability pygen_variable_caps_Matrix[] = {SpvCapabilityMatrix}; static const SpvCapability pygen_variable_caps_MemoryAccessAliasingINTEL[] = {SpvCapabilityMemoryAccessAliasingINTEL}; +static const SpvCapability pygen_variable_caps_MeshShadingEXT[] = {SpvCapabilityMeshShadingEXT}; static const SpvCapability pygen_variable_caps_MeshShadingNV[] = {SpvCapabilityMeshShadingNV}; static const SpvCapability pygen_variable_caps_NamedBarrier[] = {SpvCapabilityNamedBarrier}; static const SpvCapability pygen_variable_caps_PipeStorage[] = {SpvCapabilityPipeStorage}; @@ -493,6 +494,8 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = { {"FragmentFetchAMD", SpvOpFragmentFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu, 0xffffffffu}, {"ReadClockKHR", SpvOpReadClockKHR, 1, pygen_variable_caps_ShaderClockKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_clock, 0xffffffffu, 0xffffffffu}, {"ImageSampleFootprintNV", SpvOpImageSampleFootprintNV, 1, pygen_variable_caps_ImageFootprintNV, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_image_footprint, 0xffffffffu, 0xffffffffu}, + {"EmitMeshTasksEXT", SpvOpEmitMeshTasksEXT, 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", SpvOpSetMeshOutputsEXT, 1, pygen_variable_caps_MeshShadingEXT, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu}, {"GroupNonUniformPartitionNV", SpvOpGroupNonUniformPartitionNV, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_subgroup_partitioned, 0xffffffffu, 0xffffffffu}, {"WritePackedPrimitiveIndices4x8NV", SpvOpWritePackedPrimitiveIndices4x8NV, 1, pygen_variable_caps_MeshShadingNV, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_mesh_shader, 0xffffffffu, 0xffffffffu}, {"ReportIntersectionKHR", SpvOpReportIntersectionKHR, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 2, pygen_variable_exts_SPV_NV_ray_tracingSPV_KHR_ray_tracing, 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 a09c64af4..e2752e299 100644 --- a/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc +++ b/3rdparty/spirv-tools/include/generated/enum_string_mapping.inc @@ -22,6 +22,8 @@ const char* ExtensionToString(Extension extension) { return "SPV_AMD_shader_trinary_minmax"; case Extension::kSPV_AMD_texture_gather_bias_lod: return "SPV_AMD_texture_gather_bias_lod"; + case Extension::kSPV_ARM_core_builtins: + return "SPV_ARM_core_builtins"; case Extension::kSPV_EXT_demote_to_helper_invocation: return "SPV_EXT_demote_to_helper_invocation"; case Extension::kSPV_EXT_descriptor_indexing: @@ -32,6 +34,8 @@ const char* ExtensionToString(Extension extension) { return "SPV_EXT_fragment_invocation_density"; case Extension::kSPV_EXT_fragment_shader_interlock: return "SPV_EXT_fragment_shader_interlock"; + case Extension::kSPV_EXT_mesh_shader: + return "SPV_EXT_mesh_shader"; case Extension::kSPV_EXT_physical_storage_buffer: return "SPV_EXT_physical_storage_buffer"; case Extension::kSPV_EXT_shader_atomic_float16_add: @@ -215,8 +219,8 @@ const char* ExtensionToString(Extension extension) { bool GetExtensionFromString(const char* str, Extension* extension) { - static const char* known_ext_strs[] = { "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_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_physical_storage_buffer", "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_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_blocking_pipes", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "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_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_constant_composite", "SPV_INTEL_loop_fuse", "SPV_INTEL_media_block_io", "SPV_INTEL_memory_access_aliasing", "SPV_INTEL_optnone", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_split_barrier", "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_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_fragment_shader_barycentric", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "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_ray_cull_mask", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "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_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_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_ray_tracing_motion_blur", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" }; - static const Extension known_ext_ids[] = { 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_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_physical_storage_buffer, 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_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_blocking_pipes, 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_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, 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_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_constant_composite, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_memory_access_aliasing, Extension::kSPV_INTEL_optnone, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_split_barrier, 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_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, 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_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_ray_cull_mask, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, 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_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_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_ray_tracing_motion_blur, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, 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_VALIDATOR_ignore_type_decl_unique }; + static const char* known_ext_strs[] = { "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_core_builtins", "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_physical_storage_buffer", "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_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_blocking_pipes", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "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_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_constant_composite", "SPV_INTEL_loop_fuse", "SPV_INTEL_media_block_io", "SPV_INTEL_memory_access_aliasing", "SPV_INTEL_optnone", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_split_barrier", "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_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_fragment_shader_barycentric", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "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_ray_cull_mask", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "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_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_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_ray_tracing_motion_blur", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" }; + static const Extension known_ext_ids[] = { 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_core_builtins, 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_physical_storage_buffer, 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_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_blocking_pipes, 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_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, 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_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_constant_composite, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_memory_access_aliasing, Extension::kSPV_INTEL_optnone, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_split_barrier, 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_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, 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_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_ray_cull_mask, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, 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_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_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_ray_tracing_motion_blur, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, 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_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( @@ -372,6 +376,8 @@ const char* CapabilityToString(SpvCapability capability) { return "ShaderViewportIndex"; case SpvCapabilityUniformDecoration: return "UniformDecoration"; + case SpvCapabilityCoreBuiltinsARM: + return "CoreBuiltinsARM"; case SpvCapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR"; case SpvCapabilitySubgroupBallotKHR: @@ -462,6 +468,8 @@ const char* CapabilityToString(SpvCapability capability) { return "MeshShadingNV"; case SpvCapabilityImageFootprintNV: return "ImageFootprintNV"; + case SpvCapabilityMeshShadingEXT: + return "MeshShadingEXT"; case SpvCapabilityFragmentBarycentricKHR: return "FragmentBarycentricKHR"; case SpvCapabilityComputeDerivativeGroupQuadsNV: diff --git a/3rdparty/spirv-tools/include/generated/extension_enum.inc b/3rdparty/spirv-tools/include/generated/extension_enum.inc index 41c7927cb..ed70cefc1 100644 --- a/3rdparty/spirv-tools/include/generated/extension_enum.inc +++ b/3rdparty/spirv-tools/include/generated/extension_enum.inc @@ -9,11 +9,13 @@ kSPV_AMD_shader_fragment_mask, kSPV_AMD_shader_image_load_store_lod, kSPV_AMD_shader_trinary_minmax, kSPV_AMD_texture_gather_bias_lod, +kSPV_ARM_core_builtins, kSPV_EXT_demote_to_helper_invocation, kSPV_EXT_descriptor_indexing, kSPV_EXT_fragment_fully_covered, kSPV_EXT_fragment_invocation_density, kSPV_EXT_fragment_shader_interlock, +kSPV_EXT_mesh_shader, kSPV_EXT_physical_storage_buffer, kSPV_EXT_shader_atomic_float16_add, kSPV_EXT_shader_atomic_float_add, diff --git a/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc b/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc index 1a422d506..397f5c39d 100644 --- a/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc +++ b/3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc @@ -6,13 +6,14 @@ static const SpvCapability pygen_variable_caps_BindlessTextureNV[] = {SpvCapabil static const SpvCapability pygen_variable_caps_ClipDistance[] = {SpvCapabilityClipDistance}; static const SpvCapability pygen_variable_caps_ComputeDerivativeGroupLinearNV[] = {SpvCapabilityComputeDerivativeGroupLinearNV}; static const SpvCapability pygen_variable_caps_ComputeDerivativeGroupQuadsNV[] = {SpvCapabilityComputeDerivativeGroupQuadsNV}; +static const SpvCapability pygen_variable_caps_CoreBuiltinsARM[] = {SpvCapabilityCoreBuiltinsARM}; static const SpvCapability pygen_variable_caps_CullDistance[] = {SpvCapabilityCullDistance}; static const SpvCapability pygen_variable_caps_DenormFlushToZero[] = {SpvCapabilityDenormFlushToZero}; static const SpvCapability pygen_variable_caps_DenormPreserve[] = {SpvCapabilityDenormPreserve}; static const SpvCapability pygen_variable_caps_DeviceEnqueue[] = {SpvCapabilityDeviceEnqueue}; static const SpvCapability pygen_variable_caps_DeviceGroup[] = {SpvCapabilityDeviceGroup}; static const SpvCapability pygen_variable_caps_DrawParameters[] = {SpvCapabilityDrawParameters}; -static const SpvCapability pygen_variable_caps_DrawParametersMeshShadingNV[] = {SpvCapabilityDrawParameters, SpvCapabilityMeshShadingNV}; +static const SpvCapability pygen_variable_caps_DrawParametersMeshShadingNVMeshShadingEXT[] = {SpvCapabilityDrawParameters, SpvCapabilityMeshShadingNV, SpvCapabilityMeshShadingEXT}; static const SpvCapability pygen_variable_caps_FPFastMathModeINTEL[] = {SpvCapabilityFPFastMathModeINTEL}; static const SpvCapability pygen_variable_caps_FPGABufferLocationINTEL[] = {SpvCapabilityFPGABufferLocationINTEL}; static const SpvCapability pygen_variable_caps_FPGAClusterAttributesINTEL[] = {SpvCapabilityFPGAClusterAttributesINTEL}; @@ -31,11 +32,11 @@ static const SpvCapability pygen_variable_caps_FunctionFloatControlINTEL[] = {Sp static const SpvCapability pygen_variable_caps_FunctionPointersINTEL[] = {SpvCapabilityFunctionPointersINTEL}; static const SpvCapability pygen_variable_caps_GenericPointer[] = {SpvCapabilityGenericPointer}; static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry}; -static const SpvCapability pygen_variable_caps_GeometryMeshShadingNV[] = {SpvCapabilityGeometry, SpvCapabilityMeshShadingNV}; -static const SpvCapability pygen_variable_caps_GeometryShaderLayerShaderViewportIndexLayerEXTMeshShadingNV[] = {SpvCapabilityGeometry, SpvCapabilityShaderLayer, SpvCapabilityShaderViewportIndexLayerEXT, SpvCapabilityMeshShadingNV}; +static const SpvCapability pygen_variable_caps_GeometryMeshShadingNVMeshShadingEXT[] = {SpvCapabilityGeometry, SpvCapabilityMeshShadingNV, SpvCapabilityMeshShadingEXT}; +static const SpvCapability pygen_variable_caps_GeometryShaderLayerShaderViewportIndexLayerEXTMeshShadingNVMeshShadingEXT[] = {SpvCapabilityGeometry, SpvCapabilityShaderLayer, SpvCapabilityShaderViewportIndexLayerEXT, SpvCapabilityMeshShadingNV, SpvCapabilityMeshShadingEXT}; static const SpvCapability pygen_variable_caps_GeometryTessellation[] = {SpvCapabilityGeometry, SpvCapabilityTessellation}; -static const SpvCapability pygen_variable_caps_GeometryTessellationMeshShadingNV[] = {SpvCapabilityGeometry, SpvCapabilityTessellation, SpvCapabilityMeshShadingNV}; -static const SpvCapability pygen_variable_caps_GeometryTessellationRayTracingNVRayTracingKHRMeshShadingNV[] = {SpvCapabilityGeometry, SpvCapabilityTessellation, SpvCapabilityRayTracingNV, SpvCapabilityRayTracingKHR, SpvCapabilityMeshShadingNV}; +static const SpvCapability pygen_variable_caps_GeometryTessellationMeshShadingNVMeshShadingEXT[] = {SpvCapabilityGeometry, SpvCapabilityTessellation, SpvCapabilityMeshShadingNV, SpvCapabilityMeshShadingEXT}; +static const SpvCapability pygen_variable_caps_GeometryTessellationRayTracingNVRayTracingKHRMeshShadingNVMeshShadingEXT[] = {SpvCapabilityGeometry, SpvCapabilityTessellation, SpvCapabilityRayTracingNV, SpvCapabilityRayTracingKHR, SpvCapabilityMeshShadingNV, SpvCapabilityMeshShadingEXT}; static const SpvCapability pygen_variable_caps_GeometryShaderPassthroughNV[] = {SpvCapabilityGeometryShaderPassthroughNV}; static const SpvCapability pygen_variable_caps_GeometryStreams[] = {SpvCapabilityGeometryStreams}; static const SpvCapability pygen_variable_caps_GroupNonUniform[] = {SpvCapabilityGroupNonUniform}; @@ -61,11 +62,13 @@ static const SpvCapability pygen_variable_caps_Linkage[] = {SpvCapabilityLinkage static const SpvCapability pygen_variable_caps_LoopFuseINTEL[] = {SpvCapabilityLoopFuseINTEL}; static const SpvCapability pygen_variable_caps_Matrix[] = {SpvCapabilityMatrix}; static const SpvCapability pygen_variable_caps_MemoryAccessAliasingINTEL[] = {SpvCapabilityMemoryAccessAliasingINTEL}; +static const SpvCapability pygen_variable_caps_MeshShadingEXT[] = {SpvCapabilityMeshShadingEXT}; static const SpvCapability pygen_variable_caps_MeshShadingNV[] = {SpvCapabilityMeshShadingNV}; +static const SpvCapability pygen_variable_caps_MeshShadingNVMeshShadingEXT[] = {SpvCapabilityMeshShadingNV, SpvCapabilityMeshShadingEXT}; static const SpvCapability pygen_variable_caps_MinLod[] = {SpvCapabilityMinLod}; static const SpvCapability pygen_variable_caps_MultiView[] = {SpvCapabilityMultiView}; static const SpvCapability pygen_variable_caps_MultiViewport[] = {SpvCapabilityMultiViewport}; -static const SpvCapability pygen_variable_caps_MultiViewportShaderViewportIndexShaderViewportIndexLayerEXTMeshShadingNV[] = {SpvCapabilityMultiViewport, SpvCapabilityShaderViewportIndex, SpvCapabilityShaderViewportIndexLayerEXT, SpvCapabilityMeshShadingNV}; +static const SpvCapability pygen_variable_caps_MultiViewportShaderViewportIndexShaderViewportIndexLayerEXTMeshShadingNVMeshShadingEXT[] = {SpvCapabilityMultiViewport, SpvCapabilityShaderViewportIndex, SpvCapabilityShaderViewportIndexLayerEXT, SpvCapabilityMeshShadingNV, SpvCapabilityMeshShadingEXT}; static const SpvCapability pygen_variable_caps_OptNoneINTEL[] = {SpvCapabilityOptNoneINTEL}; static const SpvCapability pygen_variable_caps_PerViewAttributesNVMeshShadingNV[] = {SpvCapabilityPerViewAttributesNV, SpvCapabilityMeshShadingNV}; static const SpvCapability pygen_variable_caps_PhysicalStorageBufferAddresses[] = {SpvCapabilityPhysicalStorageBufferAddresses}; @@ -129,11 +132,15 @@ static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_explicit_ver static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_fragment_mask[] = {spvtools::Extension::kSPV_AMD_shader_fragment_mask}; static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_image_load_store_lod[] = {spvtools::Extension::kSPV_AMD_shader_image_load_store_lod}; static const spvtools::Extension pygen_variable_exts_SPV_AMD_texture_gather_bias_lod[] = {spvtools::Extension::kSPV_AMD_texture_gather_bias_lod}; +static const spvtools::Extension pygen_variable_exts_SPV_ARM_core_builtins[] = {spvtools::Extension::kSPV_ARM_core_builtins}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_demote_to_helper_invocation[] = {spvtools::Extension::kSPV_EXT_demote_to_helper_invocation}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_descriptor_indexing[] = {spvtools::Extension::kSPV_EXT_descriptor_indexing}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_fully_covered[] = {spvtools::Extension::kSPV_EXT_fragment_fully_covered}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate[] = {spvtools::Extension::kSPV_EXT_fragment_invocation_density, spvtools::Extension::kSPV_NV_shading_rate}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_shader_interlock[] = {spvtools::Extension::kSPV_EXT_fragment_shader_interlock}; +static const spvtools::Extension pygen_variable_exts_SPV_EXT_mesh_shader[] = {spvtools::Extension::kSPV_EXT_mesh_shader}; +static const spvtools::Extension pygen_variable_exts_SPV_EXT_mesh_shaderSPV_KHR_shader_draw_parametersSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_EXT_mesh_shader, spvtools::Extension::kSPV_KHR_shader_draw_parameters, spvtools::Extension::kSPV_NV_mesh_shader}; +static const spvtools::Extension pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_EXT_mesh_shader, spvtools::Extension::kSPV_NV_mesh_shader}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer[] = {spvtools::Extension::kSPV_EXT_physical_storage_buffer, spvtools::Extension::kSPV_KHR_physical_storage_buffer}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float16_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float16_add}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_add}; @@ -195,7 +202,6 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_atomic_count static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_draw_parameters[] = {spvtools::Extension::kSPV_KHR_shader_draw_parameters}; -static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_draw_parametersSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_KHR_shader_draw_parameters, spvtools::Extension::kSPV_NV_mesh_shader}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_storage_buffer_storage_classSPV_KHR_variable_pointers[] = {spvtools::Extension::kSPV_KHR_storage_buffer_storage_class, spvtools::Extension::kSPV_KHR_variable_pointers}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_rotate[] = {spvtools::Extension::kSPV_KHR_subgroup_rotate}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_uniform_control_flow[] = {spvtools::Extension::kSPV_KHR_subgroup_uniform_control_flow}; @@ -387,7 +393,9 @@ static const spv_operand_desc_t pygen_variable_ExecutionModelEntries[] = { {"MissNV", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"MissKHR", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"CallableNV", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, - {"CallableKHR", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu} + {"CallableKHR", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"TaskEXT", 5364, 1, pygen_variable_caps_MeshShadingEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, + {"MeshEXT", 5365, 1, pygen_variable_caps_MeshShadingEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu} }; static const spv_operand_desc_t pygen_variable_AddressingModelEntries[] = { @@ -432,8 +440,8 @@ static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = { {"InputTrianglesAdjacency", 23, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"Quads", 24, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"Isolines", 25, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, - {"OutputVertices", 26, 3, pygen_variable_caps_GeometryTessellationMeshShadingNV, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, - {"OutputPoints", 27, 2, pygen_variable_caps_GeometryMeshShadingNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"OutputVertices", 26, 4, pygen_variable_caps_GeometryTessellationMeshShadingNVMeshShadingEXT, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"OutputPoints", 27, 3, pygen_variable_caps_GeometryMeshShadingNVMeshShadingEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"OutputLineStrip", 28, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"OutputTriangleStrip", 29, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"VecTypeHint", 30, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, @@ -460,11 +468,14 @@ static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = { {"StencilRefUnchangedBackAMD", 5082, 1, pygen_variable_caps_StencilExportEXT, 2, pygen_variable_exts_SPV_AMD_shader_early_and_late_fragment_testsSPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu}, {"StencilRefGreaterBackAMD", 5083, 1, pygen_variable_caps_StencilExportEXT, 2, pygen_variable_exts_SPV_AMD_shader_early_and_late_fragment_testsSPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu}, {"StencilRefLessBackAMD", 5084, 1, pygen_variable_caps_StencilExportEXT, 2, pygen_variable_exts_SPV_AMD_shader_early_and_late_fragment_testsSPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu}, - {"OutputLinesNV", 5269, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, - {"OutputPrimitivesNV", 5270, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}, + {"OutputLinesNV", 5269, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"OutputLinesEXT", 5269, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"OutputPrimitivesNV", 5270, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}, + {"OutputPrimitivesEXT", 5270, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}, {"DerivativeGroupQuadsNV", 5289, 1, pygen_variable_caps_ComputeDerivativeGroupQuadsNV, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu}, {"DerivativeGroupLinearNV", 5290, 1, pygen_variable_caps_ComputeDerivativeGroupLinearNV, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu}, - {"OutputTrianglesNV", 5298, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"OutputTrianglesNV", 5298, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"OutputTrianglesEXT", 5298, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PixelInterlockOrderedEXT", 5366, 1, pygen_variable_caps_FragmentShaderPixelInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, {"PixelInterlockUnorderedEXT", 5367, 1, pygen_variable_caps_FragmentShaderPixelInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, {"SampleInterlockOrderedEXT", 5368, 1, pygen_variable_caps_FragmentShaderSampleInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, @@ -512,6 +523,7 @@ static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = { {"ShaderRecordBufferKHR", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"PhysicalStorageBuffer", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"PhysicalStorageBufferEXT", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, + {"TaskPayloadWorkgroupEXT", 5402, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu}, {"CodeSectionINTEL", 5605, 1, pygen_variable_caps_FunctionPointersINTEL, 1, pygen_variable_exts_SPV_INTEL_function_pointers, {}, 0xffffffffu, 0xffffffffu}, {"DeviceOnlyINTEL", 5936, 1, pygen_variable_caps_USMStorageClassesINTEL, 1, pygen_variable_exts_SPV_INTEL_usm_storage_classes, {}, 0xffffffffu, 0xffffffffu}, {"HostOnlyINTEL", 5937, 1, pygen_variable_caps_USMStorageClassesINTEL, 1, pygen_variable_exts_SPV_INTEL_usm_storage_classes, {}, 0xffffffffu, 0xffffffffu} @@ -741,9 +753,10 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = { {"PassthroughNV", 5250, 1, pygen_variable_caps_GeometryShaderPassthroughNV, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu, 0xffffffffu}, {"ViewportRelativeNV", 5252, 1, pygen_variable_caps_ShaderViewportMaskNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"SecondaryViewportRelativeNV", 5256, 1, pygen_variable_caps_ShaderStereoViewNV, 1, pygen_variable_exts_SPV_NV_stereo_view_rendering, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}, - {"PerPrimitiveNV", 5271, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"PerPrimitiveNV", 5271, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"PerPrimitiveEXT", 5271, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PerViewNV", 5272, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, - {"PerTaskNV", 5273, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"PerTaskNV", 5273, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PerVertexKHR", 5285, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu}, {"PerVertexNV", 5285, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu}, {"NonUniform", 5300, 1, pygen_variable_caps_ShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, @@ -807,10 +820,10 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = { {"CullDistance", 4, 1, pygen_variable_caps_CullDistance, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"VertexId", 5, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"InstanceId", 6, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, - {"PrimitiveId", 7, 5, pygen_variable_caps_GeometryTessellationRayTracingNVRayTracingKHRMeshShadingNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"PrimitiveId", 7, 6, pygen_variable_caps_GeometryTessellationRayTracingNVRayTracingKHRMeshShadingNVMeshShadingEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"InvocationId", 8, 2, pygen_variable_caps_GeometryTessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, - {"Layer", 9, 4, pygen_variable_caps_GeometryShaderLayerShaderViewportIndexLayerEXTMeshShadingNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, - {"ViewportIndex", 10, 4, pygen_variable_caps_MultiViewportShaderViewportIndexShaderViewportIndexLayerEXTMeshShadingNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"Layer", 9, 5, pygen_variable_caps_GeometryShaderLayerShaderViewportIndexLayerEXTMeshShadingNVMeshShadingEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"ViewportIndex", 10, 5, pygen_variable_caps_MultiViewportShaderViewportIndexShaderViewportIndexLayerEXTMeshShadingNVMeshShadingEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"TessLevelOuter", 11, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"TessLevelInner", 12, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"TessCoord", 13, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, @@ -842,6 +855,11 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = { {"SubgroupLocalInvocationId", 41, 3, pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"VertexIndex", 42, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"InstanceIndex", 43, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"CoreIDARM", 4160, 1, pygen_variable_caps_CoreBuiltinsARM, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"CoreCountARM", 4161, 1, pygen_variable_caps_CoreBuiltinsARM, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"CoreMaxIDARM", 4162, 1, pygen_variable_caps_CoreBuiltinsARM, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"WarpIDARM", 4163, 1, pygen_variable_caps_CoreBuiltinsARM, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, + {"WarpMaxIDARM", 4164, 1, pygen_variable_caps_CoreBuiltinsARM, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"SubgroupEqMask", 4416, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, {"SubgroupEqMaskKHR", 4416, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, {"SubgroupGeMask", 4417, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, @@ -854,7 +872,7 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = { {"SubgroupLtMaskKHR", 4420, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, {"BaseVertex", 4424, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, {"BaseInstance", 4425, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, - {"DrawIndex", 4426, 2, pygen_variable_caps_DrawParametersMeshShadingNV, 2, pygen_variable_exts_SPV_KHR_shader_draw_parametersSPV_NV_mesh_shader, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, + {"DrawIndex", 4426, 3, pygen_variable_caps_DrawParametersMeshShadingNVMeshShadingEXT, 3, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_KHR_shader_draw_parametersSPV_NV_mesh_shader, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, {"PrimitiveShadingRateKHR", 4432, 1, pygen_variable_caps_FragmentShadingRateKHR, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu}, {"DeviceIndex", 4438, 1, pygen_variable_caps_DeviceGroup, 1, pygen_variable_exts_SPV_KHR_device_group, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, {"ViewIndex", 4440, 1, pygen_variable_caps_MultiView, 1, pygen_variable_exts_SPV_KHR_multiview, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, @@ -889,6 +907,10 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = { {"FragmentSizeNV", 5292, 2, pygen_variable_caps_ShadingRateNVFragmentDensityEXT, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu}, {"FragInvocationCountEXT", 5293, 2, pygen_variable_caps_FragmentDensityEXTShadingRateNV, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu}, {"InvocationsPerPixelNV", 5293, 2, pygen_variable_caps_ShadingRateNVFragmentDensityEXT, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu}, + {"PrimitivePointIndicesEXT", 5294, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"PrimitiveLineIndicesEXT", 5295, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"PrimitiveTriangleIndicesEXT", 5296, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, + {"CullPrimitiveEXT", 5299, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"LaunchIdNV", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"LaunchIdKHR", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"LaunchSizeNV", 5320, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, @@ -1023,6 +1045,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = { {"ShaderLayer", 69, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"ShaderViewportIndex", 70, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"UniformDecoration", 71, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu}, + {"CoreBuiltinsARM", 4165, 0, nullptr, 1, pygen_variable_exts_SPV_ARM_core_builtins, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}, {"FragmentShadingRateKHR", 4422, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu}, {"SubgroupBallotKHR", 4423, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, 0xffffffffu, 0xffffffffu}, {"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, @@ -1071,6 +1094,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = { {"FragmentFullyCoveredEXT", 5265, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_fully_covered, {}, 0xffffffffu, 0xffffffffu}, {"MeshShadingNV", 5266, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"ImageFootprintNV", 5282, 0, nullptr, 1, pygen_variable_exts_SPV_NV_shader_image_footprint, {}, 0xffffffffu, 0xffffffffu}, + {"MeshShadingEXT", 5283, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"FragmentBarycentricKHR", 5284, 0, nullptr, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu}, {"FragmentBarycentricNV", 5284, 0, nullptr, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu}, {"ComputeDerivativeGroupQuadsNV", 5288, 0, nullptr, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu}, diff --git a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h index 811cb06a9..1643b5a9b 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h +++ b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h @@ -671,6 +671,10 @@ SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetSkipBlockLayout( SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetAllowLocalSizeId( spv_validator_options options, bool val); +// Whether friendly names should be used in validation error messages. +SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetFriendlyNames( + spv_validator_options options, bool val); + // Creates an optimizer options object with default options. Returns a valid // options object. The object remains valid until it is passed into // |spvOptimizerOptionsDestroy|. diff --git a/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp b/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp index 25eb8a1dc..408e3ebb2 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp +++ b/3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp @@ -148,6 +148,11 @@ class ValidatorOptions { spvValidatorOptionsSetBeforeHlslLegalization(options_, val); } + // Whether friendly names should be used in validation error messages. + void SetFriendlyNames(bool val) { + spvValidatorOptionsSetFriendlyNames(options_, val); + } + private: spv_validator_options options_; }; diff --git a/3rdparty/spirv-tools/source/cfa.h b/3rdparty/spirv-tools/source/cfa.h index f55a7bde6..2743ab40c 100644 --- a/3rdparty/spirv-tools/source/cfa.h +++ b/3rdparty/spirv-tools/source/cfa.h @@ -52,12 +52,37 @@ class CFA { uint32_t id); public: + /// @brief Depth first traversal starting from the \p entry BasicBlock + /// + /// This function performs a depth first traversal from the \p entry + /// BasicBlock and calls the pre/postorder functions when it needs to process + /// the node in pre order, post order. + /// + /// @param[in] entry The root BasicBlock of a CFG + /// @param[in] successor_func A function which will return a pointer to the + /// successor nodes + /// @param[in] preorder A function that will be called for every block in a + /// CFG following preorder traversal semantics + /// @param[in] postorder A function that will be called for every block in a + /// CFG following postorder traversal semantics + /// @param[in] terminal A function that will be called to determine if the + /// search should stop at the given node. + /// NOTE: The @p successor_func and predecessor_func each return a pointer to + /// a collection such that iterators to that collection remain valid for the + /// lifetime of the algorithm. + static void DepthFirstTraversal(const BB* entry, + get_blocks_func successor_func, + std::function preorder, + std::function postorder, + std::function terminal); + /// @brief Depth first traversal starting from the \p entry BasicBlock /// /// This function performs a depth first traversal from the \p entry /// BasicBlock and calls the pre/postorder functions when it needs to process /// the node in pre order, post order. It also calls the backedge function - /// when a back edge is encountered. + /// when a back edge is encountered. The backedge function can be empty. The + /// runtime of the algorithm is improved if backedge is empty. /// /// @param[in] entry The root BasicBlock of a CFG /// @param[in] successor_func A function which will return a pointer to the @@ -67,12 +92,11 @@ class CFA { /// @param[in] postorder A function that will be called for every block in a /// CFG following postorder traversal semantics /// @param[in] backedge A function that will be called when a backedge is - /// encountered during a traversal + /// encountered during a traversal. /// @param[in] terminal A function that will be called to determine if the /// search should stop at the given node. /// NOTE: The @p successor_func and predecessor_func each return a pointer to - /// a - /// collection such that iterators to that collection remain valid for the + /// a collection such that iterators to that collection remain valid for the /// lifetime of the algorithm. static void DepthFirstTraversal( const BB* entry, get_blocks_func successor_func, @@ -136,6 +160,16 @@ bool CFA::FindInWorkList(const std::vector& work_list, return false; } +template +void CFA::DepthFirstTraversal(const BB* entry, + get_blocks_func successor_func, + std::function preorder, + std::function postorder, + std::function terminal) { + DepthFirstTraversal(entry, successor_func, preorder, postorder, + /* backedge = */ {}, terminal); +} + template void CFA::DepthFirstTraversal( const BB* entry, get_blocks_func successor_func, @@ -143,6 +177,11 @@ void CFA::DepthFirstTraversal( std::function postorder, std::function backedge, std::function terminal) { + assert(successor_func && "The successor function cannot be empty."); + assert(preorder && "The preorder function cannot be empty."); + assert(postorder && "The postorder function cannot be empty."); + assert(terminal && "The terminal function cannot be empty."); + std::unordered_set processed; /// NOTE: work_list is the sequence of nodes from the root node to the node @@ -162,7 +201,7 @@ void CFA::DepthFirstTraversal( } else { BB* child = *top.iter; top.iter++; - if (FindInWorkList(work_list, child->id())) { + if (backedge && FindInWorkList(work_list, child->id())) { backedge(top.block, child); } if (processed.count(child->id()) == 0) { @@ -269,14 +308,12 @@ std::vector CFA::TraversalRoots(const std::vector& blocks, auto mark_visited = [&visited](const BB* b) { visited.insert(b); }; auto ignore_block = [](const BB*) {}; - auto ignore_blocks = [](const BB*, const BB*) {}; auto no_terminal_blocks = [](const BB*) { return false; }; auto traverse_from_root = [&mark_visited, &succ_func, &ignore_block, - &ignore_blocks, &no_terminal_blocks](const BB* entry) { DepthFirstTraversal(entry, succ_func, mark_visited, ignore_block, - ignore_blocks, no_terminal_blocks); + no_terminal_blocks); }; std::vector result; diff --git a/3rdparty/spirv-tools/source/diff/diff.cpp b/3rdparty/spirv-tools/source/diff/diff.cpp index 17750ff26..7ed41de58 100644 --- a/3rdparty/spirv-tools/source/diff/diff.cpp +++ b/3rdparty/spirv-tools/source/diff/diff.cpp @@ -1284,8 +1284,15 @@ bool Differ::MatchOpSpecConstant(const opt::Instruction* src_inst, return src_spec_id == dst_spec_id; } - // There is no spec id, this is not valid. - assert(false && "Unreachable"); + // There is no SpecId decoration, while not practical, still valid. + // SpecConstantOp don't have SpecId and can be matched by operands + if (src_inst->opcode() == SpvOpSpecConstantOp) { + if (src_inst->NumInOperandWords() == dst_inst->NumInOperandWords()) { + return DoOperandsMatch(src_inst, dst_inst, 0, + src_inst->NumInOperandWords()); + } + } + return false; } diff --git a/3rdparty/spirv-tools/source/opcode.cpp b/3rdparty/spirv-tools/source/opcode.cpp index 2584d51eb..3f927290e 100644 --- a/3rdparty/spirv-tools/source/opcode.cpp +++ b/3rdparty/spirv-tools/source/opcode.cpp @@ -453,6 +453,7 @@ bool spvOpcodeIsAbort(SpvOp opcode) { case SpvOpTerminateInvocation: case SpvOpTerminateRayKHR: case SpvOpIgnoreIntersectionKHR: + case SpvOpEmitMeshTasksEXT: return true; default: return false; @@ -467,11 +468,6 @@ bool spvOpcodeIsBlockTerminator(SpvOp opcode) { return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode); } -bool spvOpcodeTerminatesExecution(SpvOp opcode) { - return opcode == SpvOpKill || opcode == SpvOpTerminateInvocation || - opcode == SpvOpTerminateRayKHR || opcode == SpvOpIgnoreIntersectionKHR; -} - bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) { switch (opcode) { case SpvOpTypeImage: diff --git a/3rdparty/spirv-tools/source/opcode.h b/3rdparty/spirv-tools/source/opcode.h index c8525a253..77a0bed25 100644 --- a/3rdparty/spirv-tools/source/opcode.h +++ b/3rdparty/spirv-tools/source/opcode.h @@ -110,18 +110,16 @@ bool spvOpcodeIsBranch(SpvOp opcode); // Returns true if the given opcode is a return instruction. bool spvOpcodeIsReturn(SpvOp opcode); -// Returns true if the given opcode aborts execution. +// Returns true if the given opcode aborts execution. To abort means that after +// executing that instruction, no other instructions will be executed regardless +// of the context in which the instruction appears. Note that `OpUnreachable` +// is considered an abort even if its behaviour is undefined. bool spvOpcodeIsAbort(SpvOp opcode); // Returns true if the given opcode is a return instruction or it aborts // execution. bool spvOpcodeIsReturnOrAbort(SpvOp opcode); -// Returns true if the given opcode is a kill instruction or it terminates -// execution. Note that branches, returns, and unreachables do not terminate -// execution. -bool spvOpcodeTerminatesExecution(SpvOp opcode); - // Returns true if the given opcode is a basic block terminator. bool spvOpcodeIsBlockTerminator(SpvOp opcode); 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 ffb499f67..7fa5c8a95 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 @@ -338,23 +338,25 @@ void AggressiveDCEPass::ProcessWorkList(Function* func) { } } +void AggressiveDCEPass::AddDebugScopeToWorkList(const Instruction* inst) { + auto scope = inst->GetDebugScope(); + auto lex_scope_id = scope.GetLexicalScope(); + if (lex_scope_id != kNoDebugScope) + AddToWorklist(get_def_use_mgr()->GetDef(lex_scope_id)); + auto inlined_at_id = scope.GetInlinedAt(); + if (inlined_at_id != kNoInlinedAt) + AddToWorklist(get_def_use_mgr()->GetDef(inlined_at_id)); +} + void AggressiveDCEPass::AddDebugInstructionsToWorkList( const Instruction* inst) { for (auto& line_inst : inst->dbg_line_insts()) { if (line_inst.IsDebugLineInst()) { AddOperandsToWorkList(&line_inst); } + AddDebugScopeToWorkList(&line_inst); } - - if (inst->GetDebugScope().GetLexicalScope() != kNoDebugScope) { - auto* scope = - get_def_use_mgr()->GetDef(inst->GetDebugScope().GetLexicalScope()); - AddToWorklist(scope); - } - if (inst->GetDebugInlinedAt() != kNoInlinedAt) { - auto* inlined_at = get_def_use_mgr()->GetDef(inst->GetDebugInlinedAt()); - AddToWorklist(inlined_at); - } + AddDebugScopeToWorkList(inst); } void AggressiveDCEPass::AddDecorationsToWorkList(const Instruction* inst) { @@ -630,6 +632,16 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() { auto dbg_none = context()->get_debug_info_mgr()->GetDebugInfoNone(); AddToWorklist(dbg_none); } + + // Add top level DebugInfo to worklist + for (auto& dbg : get_module()->ext_inst_debuginfo()) { + auto op = dbg.GetShader100DebugOpcode(); + if (op == NonSemanticShaderDebugInfo100DebugCompilationUnit || + op == NonSemanticShaderDebugInfo100DebugEntryPoint || + op == NonSemanticShaderDebugInfo100DebugSourceContinued) { + AddToWorklist(&dbg); + } + } } Pass::Status AggressiveDCEPass::ProcessImpl() { diff --git a/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.h b/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.h index 1b3fd1e85..c1291dc47 100644 --- a/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.h +++ b/3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.h @@ -178,6 +178,9 @@ class AggressiveDCEPass : public MemPass { // Adds all decorations of |inst| to the work list. void AddDecorationsToWorkList(const Instruction* inst); + // Adds DebugScope instruction associated with |inst| to the work list. + void AddDebugScopeToWorkList(const Instruction* inst); + // Adds all debug instruction associated with |inst| to the work list. void AddDebugInstructionsToWorkList(const Instruction* inst); diff --git a/3rdparty/spirv-tools/source/opt/cfg.cpp b/3rdparty/spirv-tools/source/opt/cfg.cpp index 66b1aeda8..a0248d54c 100644 --- a/3rdparty/spirv-tools/source/opt/cfg.cpp +++ b/3rdparty/spirv-tools/source/opt/cfg.cpp @@ -87,7 +87,6 @@ void CFG::ComputeStructuredOrder(Function* func, BasicBlock* root, // Compute structured successors and do DFS. ComputeStructuredSuccessors(func); auto ignore_block = [](cbb_ptr) {}; - auto ignore_edge = [](cbb_ptr, cbb_ptr) {}; auto terminal = [end](cbb_ptr bb) { return bb == end; }; auto get_structured_successors = [this](const BasicBlock* b) { @@ -100,8 +99,7 @@ void CFG::ComputeStructuredOrder(Function* func, BasicBlock* root, order->push_front(const_cast(b)); }; CFA::DepthFirstTraversal(root, get_structured_successors, - ignore_block, post_order, ignore_edge, - terminal); + ignore_block, post_order, terminal); } void CFG::ForEachBlockInPostOrder(BasicBlock* bb, diff --git a/3rdparty/spirv-tools/source/opt/compact_ids_pass.cpp b/3rdparty/spirv-tools/source/opt/compact_ids_pass.cpp index 70848d79b..5a2a54b17 100644 --- a/3rdparty/spirv-tools/source/opt/compact_ids_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/compact_ids_pass.cpp @@ -44,6 +44,11 @@ Pass::Status CompactIdsPass::Process() { bool modified = false; std::unordered_map result_id_mapping; + // Disable automatic DebugInfo analysis for the life of the CompactIds pass. + // The DebugInfo manager requires the SPIR-V to be valid to run, but this is + // not true at all times in CompactIds as it remaps all ids. + context()->InvalidateAnalyses(IRContext::kAnalysisDebugInfo); + context()->module()->ForEachInst( [&result_id_mapping, &modified](Instruction* inst) { auto operand = inst->begin(); diff --git a/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp b/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp index cb3608747..0ad755c94 100644 --- a/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp +++ b/3rdparty/spirv-tools/source/opt/const_folding_rules.cpp @@ -74,7 +74,7 @@ bool HasFloatingPoint(const analysis::Type* type) { // Returns a constants with the value |-val| of the given type. Only works for // 32-bit and 64-bit float point types. Returns |nullptr| if an error occurs. -const analysis::Constant* negateFPConst(const analysis::Type* result_type, +const analysis::Constant* NegateFPConst(const analysis::Type* result_type, const analysis::Constant* val, analysis::ConstantManager* const_mgr) { const analysis::Float* float_type = result_type->AsFloat(); @@ -755,7 +755,7 @@ const analysis::Constant* FoldFPScalarDivideByZero( } if (numerator->AsFloatConstant()->GetValueAsDouble() < 0.0) { - result = negateFPConst(result_type, result, const_mgr); + result = NegateFPConst(result_type, result, const_mgr); } return result; } @@ -780,7 +780,7 @@ const analysis::Constant* FoldScalarFPDivide( const analysis::Constant* result = FoldFPScalarDivideByZero(result_type, numerator, const_mgr); if (result != nullptr) - result = negateFPConst(result_type, result, const_mgr); + result = NegateFPConst(result_type, result, const_mgr); return result; } else { return FOLD_FPARITH_OP(/)(result_type, numerator, denominator, const_mgr); @@ -951,7 +951,7 @@ UnaryScalarFoldingRule FoldFNegateOp() { analysis::ConstantManager* const_mgr) -> const analysis::Constant* { assert(result_type != nullptr && a != nullptr); assert(result_type == a->type()); - return negateFPConst(result_type, a, const_mgr); + return NegateFPConst(result_type, a, const_mgr); }; } @@ -1183,17 +1183,6 @@ ConstantFoldingRule FoldFMix() { }; } -template -IntType FoldIClamp(IntType x, IntType min_val, IntType max_val) { - if (x < min_val) { - x = min_val; - } - if (x > max_val) { - x = max_val; - } - return x; -} - const analysis::Constant* FoldMin(const analysis::Type* result_type, const analysis::Constant* a, const analysis::Constant* b, diff --git a/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp b/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp index 321d49692..0b235629b 100644 --- a/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp +++ b/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp @@ -151,9 +151,17 @@ Instruction* CopyPropagateArrays::BuildNewAccessChain( return source->GetVariable(); } + source->BuildConstants(); + std::vector access_ids(source->AccessChain().size()); + std::transform( + source->AccessChain().cbegin(), source->AccessChain().cend(), + access_ids.begin(), [](const AccessChainEntry& entry) { + assert(entry.is_result_id && "Constants needs to be built first."); + return entry.result_id; + }); + return builder.AddAccessChain(source->GetPointerTypeId(this), - source->GetVariable()->result_id(), - source->AccessChain()); + source->GetVariable()->result_id(), access_ids); } bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) { @@ -168,6 +176,8 @@ bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) { return false; } else if (use->opcode() == SpvOpImageTexelPointer) { return true; + } else if (use->opcode() == SpvOpEntryPoint) { + return true; } // Some other instruction. Be conservative. return false; @@ -268,30 +278,20 @@ std::unique_ptr CopyPropagateArrays::BuildMemoryObjectFromExtract(Instruction* extract_inst) { assert(extract_inst->opcode() == SpvOpCompositeExtract && "Expecting an OpCompositeExtract instruction."); - analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); - std::unique_ptr result = GetSourceObjectIfAny( extract_inst->GetSingleWordInOperand(kCompositeExtractObjectInOperand)); - if (result) { - analysis::Integer int_type(32, false); - const analysis::Type* uint32_type = - context()->get_type_mgr()->GetRegisteredType(&int_type); - - std::vector components; - // Convert the indices in the extract instruction to a series of ids that - // can be used by the |OpAccessChain| instruction. - for (uint32_t i = 1; i < extract_inst->NumInOperands(); ++i) { - uint32_t index = extract_inst->GetSingleWordInOperand(i); - const analysis::Constant* index_const = - const_mgr->GetConstant(uint32_type, {index}); - components.push_back( - const_mgr->GetDefiningInstruction(index_const)->result_id()); - } - result->GetMember(components); - return result; + if (!result) { + return nullptr; } - return nullptr; + + // Copy the indices of the extract instruction to |OpAccessChain| indices. + std::vector components; + for (uint32_t i = 1; i < extract_inst->NumInOperands(); ++i) { + components.push_back({false, {extract_inst->GetSingleWordInOperand(i)}}); + } + result->PushIndirection(components); + return result; } std::unique_ptr @@ -315,19 +315,12 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct( return nullptr; } - analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); - const analysis::Constant* last_access = - const_mgr->FindDeclaredConstant(memory_object->AccessChain().back()); - if (!last_access || !last_access->type()->AsInteger()) { + AccessChainEntry last_access = memory_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(last_access, 0)) { return nullptr; } - if (last_access->GetU32() != 0) { - return nullptr; - } - - memory_object->GetParent(); - + memory_object->PopIndirection(); if (memory_object->GetNumberOfMembers() != conststruct_inst->NumInOperands()) { return nullptr; @@ -349,13 +342,8 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct( return nullptr; } - last_access = - const_mgr->FindDeclaredConstant(member_object->AccessChain().back()); - if (!last_access || !last_access->type()->AsInteger()) { - return nullptr; - } - - if (last_access->GetU32() != i) { + last_access = member_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(last_access, i)) { return nullptr; } } @@ -409,17 +397,12 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { return nullptr; } - const analysis::Constant* last_access = - const_mgr->FindDeclaredConstant(memory_object->AccessChain().back()); - if (!last_access || !last_access->type()->AsInteger()) { + AccessChainEntry last_access = memory_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(last_access, number_of_elements - 1)) { return nullptr; } - if (last_access->GetU32() != number_of_elements - 1) { - return nullptr; - } - - memory_object->GetParent(); + memory_object->PopIndirection(); Instruction* current_insert = def_use_mgr->GetDef(insert_inst->GetSingleWordInOperand(1)); @@ -456,14 +439,9 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { return nullptr; } - const analysis::Constant* current_last_access = - const_mgr->FindDeclaredConstant( - current_memory_object->AccessChain().back()); - if (!current_last_access || !current_last_access->type()->AsInteger()) { - return nullptr; - } - - if (current_last_access->GetU32() != i - 1) { + AccessChainEntry current_last_access = + current_memory_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(current_last_access, i - 1)) { return nullptr; } current_insert = @@ -473,6 +451,21 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { return memory_object; } +bool CopyPropagateArrays::IsAccessChainIndexValidAndEqualTo( + const AccessChainEntry& entry, uint32_t value) const { + if (!entry.is_result_id) { + return entry.immediate == value; + } + + analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); + const analysis::Constant* constant = + const_mgr->FindDeclaredConstant(entry.result_id); + if (!constant || !constant->type()->AsInteger()) { + return false; + } + return constant->GetU32() == value; +} + bool CopyPropagateArrays::IsPointerToArrayType(uint32_t type_id) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::Pointer* pointer_type = type_mgr->GetType(type_id)->AsPointer(); @@ -530,6 +523,12 @@ bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst, // Variable index means the type is a type where every element // is the same type. Use element 0 to get the type. access_chain.push_back(0); + + // We are trying to access a struct with variable indices. + // This cannot happen. + if (pointee_type->kind() == analysis::Type::kStruct) { + return false; + } } } @@ -785,8 +784,8 @@ uint32_t CopyPropagateArrays::GetMemberTypeId( return id; } -void CopyPropagateArrays::MemoryObject::GetMember( - const std::vector& access_chain) { +void CopyPropagateArrays::MemoryObject::PushIndirection( + const std::vector& access_chain) { access_chain_.insert(access_chain_.end(), access_chain.begin(), access_chain.end()); } @@ -821,23 +820,29 @@ uint32_t CopyPropagateArrays::MemoryObject::GetNumberOfMembers() { template CopyPropagateArrays::MemoryObject::MemoryObject(Instruction* var_inst, iterator begin, iterator end) - : variable_inst_(var_inst), access_chain_(begin, end) {} + : variable_inst_(var_inst) { + std::transform(begin, end, std::back_inserter(access_chain_), + [](uint32_t id) { + return AccessChainEntry{true, {id}}; + }); +} std::vector CopyPropagateArrays::MemoryObject::GetAccessIds() const { analysis::ConstantManager* const_mgr = variable_inst_->context()->get_constant_mgr(); - std::vector access_indices; - for (uint32_t id : AccessChain()) { - const analysis::Constant* element_index_const = - const_mgr->FindDeclaredConstant(id); - if (!element_index_const) { - access_indices.push_back(0); - } else { - access_indices.push_back(element_index_const->GetU32()); - } - } - return access_indices; + std::vector indices(AccessChain().size()); + std::transform(AccessChain().cbegin(), AccessChain().cend(), indices.begin(), + [&const_mgr](const AccessChainEntry& entry) { + if (entry.is_result_id) { + const analysis::Constant* constant = + const_mgr->FindDeclaredConstant(entry.result_id); + return constant == nullptr ? 0 : constant->GetU32(); + } + + return entry.immediate; + }); + return indices; } bool CopyPropagateArrays::MemoryObject::Contains( @@ -858,5 +863,24 @@ bool CopyPropagateArrays::MemoryObject::Contains( return true; } +void CopyPropagateArrays::MemoryObject::BuildConstants() { + for (auto& entry : access_chain_) { + if (entry.is_result_id) { + continue; + } + + auto context = variable_inst_->context(); + analysis::Integer int_type(32, false); + const analysis::Type* uint32_type = + context->get_type_mgr()->GetRegisteredType(&int_type); + analysis::ConstantManager* const_mgr = context->get_constant_mgr(); + const analysis::Constant* index_const = + const_mgr->GetConstant(uint32_type, {entry.immediate}); + entry.result_id = + const_mgr->GetDefiningInstruction(index_const)->result_id(); + entry.is_result_id = true; + } +} + } // namespace opt } // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/copy_prop_arrays.h b/3rdparty/spirv-tools/source/opt/copy_prop_arrays.h index 46a508cfa..9e7641f61 100644 --- a/3rdparty/spirv-tools/source/opt/copy_prop_arrays.h +++ b/3rdparty/spirv-tools/source/opt/copy_prop_arrays.h @@ -52,6 +52,22 @@ class CopyPropagateArrays : public MemPass { } private: + // Represents one index in the OpAccessChain instruction. It can be either + // an instruction's result_id (OpConstant by ex), or a immediate value. + // Immediate values are used to prepare the final access chain without + // creating OpConstant instructions until done. + struct AccessChainEntry { + bool is_result_id; + union { + uint32_t result_id; + uint32_t immediate; + }; + + bool operator!=(const AccessChainEntry& other) const { + return other.is_result_id != is_result_id || other.result_id != result_id; + } + }; + // The class used to identify a particular memory object. This memory object // will be owned by a particular variable, meaning that the memory is part of // that variable. It could be the entire variable or a member of the @@ -70,12 +86,12 @@ class CopyPropagateArrays : public MemPass { // (starting from the current member). The elements in |access_chain| are // interpreted the same as the indices in the |OpAccessChain| // instruction. - void GetMember(const std::vector& access_chain); + void PushIndirection(const std::vector& access_chain); // Change |this| to now represent the first enclosing object to which it // belongs. (Remove the last element off the access_chain). It is invalid // to call this function if |this| does not represent a member of its owner. - void GetParent() { + void PopIndirection() { assert(IsMember()); access_chain_.pop_back(); } @@ -95,7 +111,13 @@ class CopyPropagateArrays : public MemPass { // member that |this| represents starting from the owning variable. These // values are to be interpreted the same way the indices are in an // |OpAccessChain| instruction. - const std::vector& AccessChain() const { return access_chain_; } + const std::vector& AccessChain() const { + return access_chain_; + } + + // Converts all immediate values in the AccessChain their OpConstant + // equivalent. + void BuildConstants(); // Returns the type id of the pointer type that can be used to point to this // memory object. @@ -137,7 +159,7 @@ class CopyPropagateArrays : public MemPass { // The access chain to reach the particular member the memory object // represents. It should be interpreted the same way the indices in an // |OpAccessChain| are interpreted. - std::vector access_chain_; + std::vector access_chain_; std::vector GetAccessIds() const; }; @@ -192,10 +214,14 @@ class CopyPropagateArrays : public MemPass { std::unique_ptr BuildMemoryObjectFromInsert( Instruction* insert_inst); + // Return true if the given entry can represent the given value. + bool IsAccessChainIndexValidAndEqualTo(const AccessChainEntry& entry, + uint32_t value) const; + // Return true if |type_id| is a pointer type whose pointee type is an array. bool IsPointerToArrayType(uint32_t type_id); - // Returns true of there are not stores using |ptr_inst| or something derived + // Returns true if there are not stores using |ptr_inst| or something derived // from it. bool HasNoStores(Instruction* ptr_inst); diff --git a/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp index cc616ca6e..d99b7f78a 100644 --- a/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/dead_branch_elim_pass.cpp @@ -459,17 +459,8 @@ void DeadBranchElimPass::FixBlockOrder() { }; // Reorders blocks according to structured order. - ProcessFunction reorder_structured = [this](Function* function) { - std::list order; - context()->cfg()->ComputeStructuredOrder(function, &*function->begin(), - &order); - std::vector blocks; - for (auto block : order) { - blocks.push_back(block); - } - for (uint32_t i = 1; i < blocks.size(); ++i) { - function->MoveBasicBlockToAfter(blocks[i]->id(), blocks[i - 1]); - } + ProcessFunction reorder_structured = [](Function* function) { + function->ReorderBasicBlocksInStructuredOrder(); return true; }; diff --git a/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp b/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp index c1df6258b..3585186f4 100644 --- a/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp +++ b/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp @@ -1,4 +1,5 @@ -// Copyright (c) 2020 Google LLC +// Copyright (c) 2020-2022 Google LLC +// Copyright (c) 2022 LunarG Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,6 +25,7 @@ static const uint32_t kOpLineOperandLineIndex = 1; static const uint32_t kLineOperandIndexDebugFunction = 7; static const uint32_t kLineOperandIndexDebugLexicalBlock = 5; +static const uint32_t kLineOperandIndexDebugLine = 5; static const uint32_t kDebugFunctionOperandFunctionIndex = 13; static const uint32_t kDebugFunctionDefinitionOperandDebugFunctionIndex = 4; static const uint32_t kDebugFunctionDefinitionOperandOpFunctionIndex = 5; @@ -210,7 +212,15 @@ uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line, break; } } else { - line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex); + if (line->opcode() == SpvOpLine) { + line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex); + } else if (line->GetShader100DebugOpcode() == + NonSemanticShaderDebugInfo100DebugLine) { + line_number = line->GetSingleWordOperand(kLineOperandIndexDebugLine); + } else { + assert(false && + "Unreachable. A line instruction must be OpLine or DebugLine"); + } // If we need the line number as an ID, generate that constant now. // If Constant or DefUse managers are invalid, generate constant @@ -219,7 +229,8 @@ uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line, // DefUse manager which cannot be done during inlining. The extra // constants that may be generated here is likely not significant // and will likely be cleaned up in later passes. - if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID) { + if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID && + line->opcode() == SpvOpLine) { if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse) || !context()->AreAnalysesValid(IRContext::Analysis::kAnalysisConstants)) line_number = AddNewConstInGlobals(context(), line_number); @@ -546,10 +557,10 @@ bool DebugInfoManager::IsDeclareVisibleToInstr(Instruction* dbg_declare, return false; } -bool DebugInfoManager::AddDebugValueIfVarDeclIsVisible( - Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id, - Instruction* insert_pos, - std::unordered_set* invisible_decls) { +bool DebugInfoManager::AddDebugValueForVariable(Instruction* scope_and_line, + uint32_t variable_id, + uint32_t value_id, + Instruction* insert_pos) { assert(scope_and_line != nullptr); auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id); @@ -557,11 +568,6 @@ bool DebugInfoManager::AddDebugValueIfVarDeclIsVisible( bool modified = false; for (auto* dbg_decl_or_val : dbg_decl_itr->second) { - if (!IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) { - if (invisible_decls) invisible_decls->insert(dbg_decl_or_val); - continue; - } - // Avoid inserting the new DebugValue between OpPhi or OpVariable // instructions. Instruction* insert_before = insert_pos->NextNode(); @@ -849,7 +855,7 @@ void DebugInfoManager::ClearDebugInfo(Instruction* instr) { fn_id_to_dbg_fn_.erase(fn_id); } if (instr->GetShader100DebugOpcode() == - NonSemanticShaderDebugInfo100DebugFunction) { + NonSemanticShaderDebugInfo100DebugFunctionDefinition) { auto fn_id = instr->GetSingleWordOperand( kDebugFunctionDefinitionOperandOpFunctionIndex); fn_id_to_dbg_fn_.erase(fn_id); diff --git a/3rdparty/spirv-tools/source/opt/debug_info_manager.h b/3rdparty/spirv-tools/source/opt/debug_info_manager.h index df34b30f4..abb7b9a08 100644 --- a/3rdparty/spirv-tools/source/opt/debug_info_manager.h +++ b/3rdparty/spirv-tools/source/opt/debug_info_manager.h @@ -15,6 +15,7 @@ #ifndef SOURCE_OPT_DEBUG_INFO_MANAGER_H_ #define SOURCE_OPT_DEBUG_INFO_MANAGER_H_ +#include #include #include @@ -144,12 +145,10 @@ class DebugInfoManager { // Generates a DebugValue instruction with value |value_id| for every local // variable that is in the scope of |scope_and_line| and whose memory is // |variable_id| and inserts it after the instruction |insert_pos|. - // Returns whether a DebugValue is added or not. |invisible_decls| returns - // DebugDeclares invisible to |scope_and_line|. - bool AddDebugValueIfVarDeclIsVisible( - Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id, - Instruction* insert_pos, - std::unordered_set* invisible_decls); + // Returns whether a DebugValue is added or not. + bool AddDebugValueForVariable(Instruction* scope_and_line, + uint32_t variable_id, uint32_t value_id, + Instruction* insert_pos); // Creates a DebugValue for DebugDeclare |dbg_decl| and inserts it before // |insert_before|. The new DebugValue has the same line and scope as @@ -244,9 +243,18 @@ class DebugInfoManager { // operand is the function. std::unordered_map fn_id_to_dbg_fn_; + // Orders Instruction* for use in associative containers (i.e. less than + // ordering). Unique Id is used. + typedef Instruction* InstPtr; + struct InstPtrLess { + bool operator()(const InstPtr& lhs, const InstPtr& rhs) const { + return lhs->unique_id() < rhs->unique_id(); + } + }; + // Mapping from variable or value ids to DebugDeclare or DebugValue // instructions whose operand is the variable or value. - std::unordered_map> + std::unordered_map> var_id_to_dbg_decl_; // Mapping from DebugScope ids to users. diff --git a/3rdparty/spirv-tools/source/opt/dominator_tree.cpp b/3rdparty/spirv-tools/source/opt/dominator_tree.cpp index d6017bb19..2680be2af 100644 --- a/3rdparty/spirv-tools/source/opt/dominator_tree.cpp +++ b/3rdparty/spirv-tools/source/opt/dominator_tree.cpp @@ -57,10 +57,8 @@ template static void DepthFirstSearch(const BBType* bb, SuccessorLambda successors, PreLambda pre, PostLambda post) { - // Ignore backedge operation. - auto nop_backedge = [](const BBType*, const BBType*) {}; auto no_terminal_blocks = [](const BBType*) { return false; }; - CFA::DepthFirstTraversal(bb, successors, pre, post, nop_backedge, + CFA::DepthFirstTraversal(bb, successors, pre, post, no_terminal_blocks); } @@ -105,7 +103,8 @@ class BasicBlockSuccessorHelper { using Function = typename GetFunctionClass::FunctionType; using BasicBlockListTy = std::vector; - using BasicBlockMapTy = std::map; + using BasicBlockMapTy = + std::unordered_map; public: // For compliance with the dominance tree computation, entry nodes are @@ -160,19 +159,7 @@ BasicBlockSuccessorHelper::BasicBlockSuccessorHelper( template void BasicBlockSuccessorHelper::CreateSuccessorMap( Function& f, const BasicBlock* placeholder_start_node) { - std::map id_to_BB_map; - auto GetSuccessorBasicBlock = [&f, &id_to_BB_map](uint32_t successor_id) { - BasicBlock*& Succ = id_to_BB_map[successor_id]; - if (!Succ) { - for (BasicBlock& BBIt : f) { - if (successor_id == BBIt.id()) { - Succ = &BBIt; - break; - } - } - } - return Succ; - }; + IRContext* context = f.DefInst().context(); if (invert_graph_) { // For the post dominator tree, we see the inverted graph. @@ -186,9 +173,8 @@ void BasicBlockSuccessorHelper::CreateSuccessorMap( BasicBlockListTy& pred_list = predecessors_[&bb]; const auto& const_bb = bb; const_bb.ForEachSuccessorLabel( - [this, &pred_list, &bb, - &GetSuccessorBasicBlock](const uint32_t successor_id) { - BasicBlock* succ = GetSuccessorBasicBlock(successor_id); + [this, &pred_list, &bb, context](const uint32_t successor_id) { + BasicBlock* succ = context->get_instr_block(successor_id); // Inverted graph: our successors in the CFG // are our predecessors in the inverted graph. this->successors_[succ].push_back(&bb); @@ -209,7 +195,7 @@ void BasicBlockSuccessorHelper::CreateSuccessorMap( const auto& const_bb = bb; const_bb.ForEachSuccessorLabel([&](const uint32_t successor_id) { - BasicBlock* succ = GetSuccessorBasicBlock(successor_id); + BasicBlock* succ = context->get_instr_block(successor_id); succ_list.push_back(succ); predecessors_[succ].push_back(&bb); }); diff --git a/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.cpp b/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.cpp index f383136d5..aa2776bbd 100644 --- a/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.cpp @@ -56,21 +56,30 @@ Pass::Status EliminateDeadInputComponentsPass::Process() { continue; } const analysis::Array* arr_type = ptr_type->pointee_type()->AsArray(); - if (arr_type == nullptr) { + if (arr_type != nullptr) { + unsigned arr_len_id = arr_type->LengthId(); + Instruction* arr_len_inst = def_use_mgr->GetDef(arr_len_id); + if (arr_len_inst->opcode() != SpvOpConstant) { + continue; + } + // SPIR-V requires array size is >= 1, so this works for signed or + // unsigned size + unsigned original_max = + arr_len_inst->GetSingleWordInOperand(kConstantValueInIdx) - 1; + unsigned max_idx = FindMaxIndex(var, original_max); + if (max_idx != original_max) { + ChangeArrayLength(var, max_idx + 1); + modified = true; + } continue; } - unsigned arr_len_id = arr_type->LengthId(); - Instruction* arr_len_inst = def_use_mgr->GetDef(arr_len_id); - if (arr_len_inst->opcode() != SpvOpConstant) { - continue; - } - // SPIR-V requires array size is >= 1, so this works for signed or - // unsigned size - unsigned original_max = - arr_len_inst->GetSingleWordInOperand(kConstantValueInIdx) - 1; + const analysis::Struct* struct_type = ptr_type->pointee_type()->AsStruct(); + if (struct_type == nullptr) continue; + const auto elt_types = struct_type->element_types(); + unsigned original_max = static_cast(elt_types.size()) - 1; unsigned max_idx = FindMaxIndex(var, original_max); if (max_idx != original_max) { - ChangeArrayLength(var, max_idx + 1); + ChangeStructLength(var, max_idx + 1); modified = true; } } @@ -116,12 +125,13 @@ unsigned EliminateDeadInputComponentsPass::FindMaxIndex(Instruction& var, return seen_non_const_ac ? original_max : max; } -void EliminateDeadInputComponentsPass::ChangeArrayLength(Instruction& arr, +void EliminateDeadInputComponentsPass::ChangeArrayLength(Instruction& arr_var, unsigned length) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); - analysis::Pointer* ptr_type = type_mgr->GetType(arr.type_id())->AsPointer(); + analysis::Pointer* ptr_type = + type_mgr->GetType(arr_var.type_id())->AsPointer(); const analysis::Array* arr_ty = ptr_type->pointee_type()->AsArray(); assert(arr_ty && "expecting array type"); uint32_t length_id = const_mgr->GetUIntConst(length); @@ -131,15 +141,48 @@ void EliminateDeadInputComponentsPass::ChangeArrayLength(Instruction& arr, analysis::Pointer new_ptr_ty(reg_new_arr_ty, SpvStorageClassInput); analysis::Type* reg_new_ptr_ty = type_mgr->GetRegisteredType(&new_ptr_ty); uint32_t new_ptr_ty_id = type_mgr->GetTypeInstruction(reg_new_ptr_ty); - arr.SetResultType(new_ptr_ty_id); - def_use_mgr->AnalyzeInstUse(&arr); - // Move array OpVariable instruction after its new type to preserve order - USE_ASSERT(arr.GetSingleWordInOperand(kVariableStorageClassInIdx) != + arr_var.SetResultType(new_ptr_ty_id); + def_use_mgr->AnalyzeInstUse(&arr_var); + // Move arr_var after its new type to preserve order + USE_ASSERT(arr_var.GetSingleWordInOperand(kVariableStorageClassInIdx) != SpvStorageClassFunction && "cannot move Function variable"); Instruction* new_ptr_ty_inst = def_use_mgr->GetDef(new_ptr_ty_id); - arr.RemoveFromList(); - arr.InsertAfter(new_ptr_ty_inst); + arr_var.RemoveFromList(); + arr_var.InsertAfter(new_ptr_ty_inst); +} + +void EliminateDeadInputComponentsPass::ChangeStructLength( + Instruction& struct_var, unsigned length) { + analysis::TypeManager* type_mgr = context()->get_type_mgr(); + analysis::Pointer* ptr_type = + type_mgr->GetType(struct_var.type_id())->AsPointer(); + const analysis::Struct* struct_ty = ptr_type->pointee_type()->AsStruct(); + assert(struct_ty && "expecting struct type"); + const auto orig_elt_types = struct_ty->element_types(); + std::vector new_elt_types; + for (unsigned u = 0; u < length; ++u) + new_elt_types.push_back(orig_elt_types[u]); + analysis::Struct new_struct_ty(new_elt_types); + analysis::Type* reg_new_struct_ty = + type_mgr->GetRegisteredType(&new_struct_ty); + uint32_t new_struct_ty_id = type_mgr->GetTypeInstruction(reg_new_struct_ty); + uint32_t old_struct_ty_id = type_mgr->GetTypeInstruction(struct_ty); + analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr(); + deco_mgr->CloneDecorations(old_struct_ty_id, new_struct_ty_id); + analysis::Pointer new_ptr_ty(reg_new_struct_ty, SpvStorageClassInput); + analysis::Type* reg_new_ptr_ty = type_mgr->GetRegisteredType(&new_ptr_ty); + uint32_t new_ptr_ty_id = type_mgr->GetTypeInstruction(reg_new_ptr_ty); + struct_var.SetResultType(new_ptr_ty_id); + analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); + def_use_mgr->AnalyzeInstUse(&struct_var); + // Move struct_var after its new type to preserve order + USE_ASSERT(struct_var.GetSingleWordInOperand(kVariableStorageClassInIdx) != + SpvStorageClassFunction && + "cannot move Function variable"); + Instruction* new_ptr_ty_inst = def_use_mgr->GetDef(new_ptr_ty_id); + struct_var.RemoveFromList(); + struct_var.InsertAfter(new_ptr_ty_inst); } } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.h b/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.h index b77857f4e..a3a133c2b 100644 --- a/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.h +++ b/3rdparty/spirv-tools/source/opt/eliminate_dead_input_components_pass.h @@ -30,7 +30,10 @@ class EliminateDeadInputComponentsPass : public Pass { public: explicit EliminateDeadInputComponentsPass() {} - const char* name() const override { return "reduce-load-size"; } + const char* name() const override { + return "eliminate-dead-input-components"; + } + Status Process() override; // Return the mask of preserved Analyses. @@ -51,6 +54,9 @@ class EliminateDeadInputComponentsPass : public Pass { // Change the length of the array |inst| to |length| void ChangeArrayLength(Instruction& inst, unsigned length); + + // Change the length of the struct |struct_var| to |length| + void ChangeStructLength(Instruction& struct_var, unsigned length); }; } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/fold.cpp b/3rdparty/spirv-tools/source/opt/fold.cpp index b903da6a2..315741ad7 100644 --- a/3rdparty/spirv-tools/source/opt/fold.cpp +++ b/3rdparty/spirv-tools/source/opt/fold.cpp @@ -627,8 +627,7 @@ Instruction* InstructionFolder::FoldInstructionToConstant( Instruction* inst, std::function id_map) const { analysis::ConstantManager* const_mgr = context_->get_constant_mgr(); - if (!inst->IsFoldableByFoldScalar() && - !GetConstantFoldingRules().HasFoldingRule(inst)) { + if (!inst->IsFoldableByFoldScalar() && !HasConstFoldingRule(inst)) { return nullptr; } // Collect the values of the constant parameters. diff --git a/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp b/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp index 85f11fdea..7a5187010 100644 --- a/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.cpp @@ -28,6 +28,7 @@ namespace opt { Pass::Status FoldSpecConstantOpAndCompositePass::Process() { bool modified = false; + analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); // Traverse through all the constant defining instructions. For Normal // Constants whose values are determined and do not depend on OpUndef // instructions, records their values in two internal maps: id_to_const_val_ @@ -62,8 +63,8 @@ Pass::Status FoldSpecConstantOpAndCompositePass::Process() { // used in OpSpecConstant{Composite|Op} instructions. // TODO(qining): If the constant or its type has decoration, we may need // to skip it. - if (context()->get_constant_mgr()->GetType(inst) && - !context()->get_constant_mgr()->GetType(inst)->decoration_empty()) + if (const_mgr->GetType(inst) && + !const_mgr->GetType(inst)->decoration_empty()) continue; switch (SpvOp opcode = inst->opcode()) { // Records the values of Normal Constants. @@ -80,15 +81,14 @@ Pass::Status FoldSpecConstantOpAndCompositePass::Process() { // Constant will be turned in to a Normal Constant. In that case, a // Constant instance should also be created successfully and recorded // in the id_to_const_val_ and const_val_to_id_ mapps. - if (auto const_value = - context()->get_constant_mgr()->GetConstantFromInst(inst)) { + if (auto const_value = const_mgr->GetConstantFromInst(inst)) { // Need to replace the OpSpecConstantComposite instruction with a // corresponding OpConstantComposite instruction. if (opcode == SpvOp::SpvOpSpecConstantComposite) { inst->SetOpcode(SpvOp::SpvOpConstantComposite); modified = true; } - context()->get_constant_mgr()->MapConstantToInst(const_value, inst); + const_mgr->MapConstantToInst(const_value, inst); } break; } @@ -144,17 +144,9 @@ bool FoldSpecConstantOpAndCompositePass::ProcessOpSpecConstantOp( return true; } -uint32_t FoldSpecConstantOpAndCompositePass::GetTypeComponent( - uint32_t typeId, uint32_t element) const { - Instruction* type = context()->get_def_use_mgr()->GetDef(typeId); - uint32_t subtype = type->GetTypeComponent(element); - assert(subtype != 0); - - return subtype; -} - Instruction* FoldSpecConstantOpAndCompositePass::FoldWithInstructionFolder( Module::inst_iterator* inst_iter_ptr) { + analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); // If one of operands to the instruction is not a // constant, then we cannot fold this spec constant. for (uint32_t i = 1; i < (*inst_iter_ptr)->NumInOperands(); i++) { @@ -164,7 +156,7 @@ Instruction* FoldSpecConstantOpAndCompositePass::FoldWithInstructionFolder( continue; } uint32_t id = operand.words[0]; - if (context()->get_constant_mgr()->FindDeclaredConstant(id) == nullptr) { + if (const_mgr->FindDeclaredConstant(id) == nullptr) { return nullptr; } } @@ -211,89 +203,10 @@ Instruction* FoldSpecConstantOpAndCompositePass::FoldWithInstructionFolder( new_const_inst->InsertAfter(insert_pos); get_def_use_mgr()->AnalyzeInstDefUse(new_const_inst); } + const_mgr->MapInst(new_const_inst); return new_const_inst; } -Instruction* FoldSpecConstantOpAndCompositePass::DoVectorShuffle( - Module::inst_iterator* pos) { - Instruction* inst = &**pos; - analysis::Vector* result_vec_type = - context()->get_constant_mgr()->GetType(inst)->AsVector(); - assert(inst->NumInOperands() - 1 > 2 && - "OpSpecConstantOp DoVectorShuffle instruction requires more than 2 " - "operands (2 vector ids and at least one literal operand"); - assert(result_vec_type && - "The result of VectorShuffle must be of type vector"); - - // A temporary null constants that can be used as the components of the result - // vector. This is needed when any one of the vector operands are null - // constant. - const analysis::Constant* null_component_constants = nullptr; - - // Get a concatenated vector of scalar constants. The vector should be built - // with the components from the first and the second operand of VectorShuffle. - std::vector concatenated_components; - // Note that for OpSpecConstantOp, the second in-operand is the first id - // operand. The first in-operand is the spec opcode. - for (uint32_t i : {1, 2}) { - assert(inst->GetInOperand(i).type == SPV_OPERAND_TYPE_ID && - "The vector operand must have a SPV_OPERAND_TYPE_ID type"); - uint32_t operand_id = inst->GetSingleWordInOperand(i); - auto operand_const = - context()->get_constant_mgr()->FindDeclaredConstant(operand_id); - if (!operand_const) return nullptr; - const analysis::Type* operand_type = operand_const->type(); - assert(operand_type->AsVector() && - "The first two operand of VectorShuffle must be of vector type"); - if (auto vec_const = operand_const->AsVectorConstant()) { - // case 1: current operand is a non-null vector constant. - concatenated_components.insert(concatenated_components.end(), - vec_const->GetComponents().begin(), - vec_const->GetComponents().end()); - } else if (operand_const->AsNullConstant()) { - // case 2: current operand is a null vector constant. Create a temporary - // null scalar constant as the component. - if (!null_component_constants) { - const analysis::Type* component_type = - operand_type->AsVector()->element_type(); - null_component_constants = - context()->get_constant_mgr()->GetConstant(component_type, {}); - } - // Append the null scalar consts to the concatenated components - // vector. - concatenated_components.insert(concatenated_components.end(), - operand_type->AsVector()->element_count(), - null_component_constants); - } else { - // no other valid cases - return nullptr; - } - } - // Create null component constants if there are any. The component constants - // must be added to the module before the dependee composite constants to - // satisfy SSA def-use dominance. - if (null_component_constants) { - context()->get_constant_mgr()->BuildInstructionAndAddToModule( - null_component_constants, pos); - } - // Create the new vector constant with the selected components. - std::vector selected_components; - for (uint32_t i = 3; i < inst->NumInOperands(); i++) { - assert(inst->GetInOperand(i).type == SPV_OPERAND_TYPE_LITERAL_INTEGER && - "The literal operand must of type SPV_OPERAND_TYPE_LITERAL_INTEGER"); - uint32_t literal = inst->GetSingleWordInOperand(i); - assert(literal < concatenated_components.size() && - "Literal index out of bound of the concatenated vector"); - selected_components.push_back(concatenated_components[literal]); - } - auto new_vec_const = MakeUnique( - result_vec_type, selected_components); - auto reg_vec_const = - context()->get_constant_mgr()->RegisterConstant(std::move(new_vec_const)); - return context()->get_constant_mgr()->BuildInstructionAndAddToModule( - reg_vec_const, pos); -} - namespace { // A helper function to check the type for component wise operations. Returns // true if the type: @@ -374,8 +287,8 @@ utils::SmallVector EncodeIntegerAsWords(const analysis::Type& type, Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation( Module::inst_iterator* pos) { const Instruction* inst = &**pos; - const analysis::Type* result_type = - context()->get_constant_mgr()->GetType(inst); + analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); + const analysis::Type* result_type = const_mgr->GetType(inst); SpvOp spec_opcode = static_cast(inst->GetSingleWordInOperand(0)); // Check and collect operands. std::vector operands; @@ -400,10 +313,9 @@ Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation( // Scalar operation const uint32_t result_val = context()->get_instruction_folder().FoldScalars(spec_opcode, operands); - auto result_const = context()->get_constant_mgr()->GetConstant( + auto result_const = const_mgr->GetConstant( result_type, EncodeIntegerAsWords(*result_type, result_val)); - return context()->get_constant_mgr()->BuildInstructionAndAddToModule( - result_const, pos); + return const_mgr->BuildInstructionAndAddToModule(result_const, pos); } else if (result_type->AsVector()) { // Vector operation const analysis::Type* element_type = @@ -414,11 +326,10 @@ Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation( operands); std::vector result_vector_components; for (const uint32_t r : result_vec) { - if (auto rc = context()->get_constant_mgr()->GetConstant( + if (auto rc = const_mgr->GetConstant( element_type, EncodeIntegerAsWords(*element_type, r))) { result_vector_components.push_back(rc); - if (!context()->get_constant_mgr()->BuildInstructionAndAddToModule( - rc, pos)) { + if (!const_mgr->BuildInstructionAndAddToModule(rc, pos)) { assert(false && "Failed to build and insert constant declaring instruction " "for the given vector component constant"); @@ -429,10 +340,8 @@ Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation( } auto new_vec_const = MakeUnique( result_type->AsVector(), result_vector_components); - auto reg_vec_const = context()->get_constant_mgr()->RegisterConstant( - std::move(new_vec_const)); - return context()->get_constant_mgr()->BuildInstructionAndAddToModule( - reg_vec_const, pos); + auto reg_vec_const = const_mgr->RegisterConstant(std::move(new_vec_const)); + return const_mgr->BuildInstructionAndAddToModule(reg_vec_const, pos); } else { // Cannot process invalid component wise operation. The result of component // wise operation must be of integer or bool scalar or vector of diff --git a/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.h b/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.h index 361d3cacb..9a8fb403d 100644 --- a/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.h +++ b/3rdparty/spirv-tools/source/opt/fold_spec_constant_op_and_composite_pass.h @@ -58,22 +58,11 @@ class FoldSpecConstantOpAndCompositePass : public Pass { // |inst_iter_ptr| using the instruction folder. Instruction* FoldWithInstructionFolder(Module::inst_iterator* inst_iter_ptr); - // Try to fold the OpSpecConstantOp VectorShuffle instruction pointed by the - // given instruction iterator to a normal constant defining instruction. - // Returns the pointer to the new constant defining instruction if succeeded. - // Otherwise return nullptr. - Instruction* DoVectorShuffle(Module::inst_iterator* inst_iter_ptr); - // Try to fold the OpSpecConstantOp instruction // pointed by the given instruction iterator to a normal constant defining // instruction. Returns the pointer to the new constant defining instruction // if succeeded, otherwise return nullptr. Instruction* DoComponentWiseOperation(Module::inst_iterator* inst_iter_ptr); - - // Returns the |element|'th subtype of |type|. - // - // |type| must be a composite type. - uint32_t GetTypeComponent(uint32_t type, uint32_t element) const; }; } // namespace opt diff --git a/3rdparty/spirv-tools/source/opt/folding_rules.cpp b/3rdparty/spirv-tools/source/opt/folding_rules.cpp index 2d778b94a..3f10bd009 100644 --- a/3rdparty/spirv-tools/source/opt/folding_rules.cpp +++ b/3rdparty/spirv-tools/source/opt/folding_rules.cpp @@ -2748,7 +2748,8 @@ FoldingRule VectorShuffleFeedingShuffle() { if (adjustment != 0) { for (uint32_t i = 2; i < new_operands.size(); i++) { - if (inst->GetSingleWordInOperand(i) >= op0_length) { + uint32_t operand = inst->GetSingleWordInOperand(i); + if (operand >= op0_length && operand != undef_literal) { new_operands[i].words[0] -= adjustment; } } diff --git a/3rdparty/spirv-tools/source/opt/function.cpp b/3rdparty/spirv-tools/source/opt/function.cpp index 38c669510..bb51df3f9 100644 --- a/3rdparty/spirv-tools/source/opt/function.cpp +++ b/3rdparty/spirv-tools/source/opt/function.cpp @@ -270,5 +270,13 @@ std::string Function::PrettyPrint(uint32_t options) const { }); return str.str(); } + +void Function::ReorderBasicBlocksInStructuredOrder() { + std::list order; + IRContext* context = this->def_inst_->context(); + context->cfg()->ComputeStructuredOrder(this, blocks_[0].get(), &order); + ReorderBasicBlocks(order.begin(), order.end()); +} + } // namespace opt } // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/function.h b/3rdparty/spirv-tools/source/opt/function.h index 917bf5843..146cbe340 100644 --- a/3rdparty/spirv-tools/source/opt/function.h +++ b/3rdparty/spirv-tools/source/opt/function.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -180,7 +181,19 @@ class Function { // Returns true is a function declaration and not a function definition. bool IsDeclaration() { return begin() == end(); } + // Reorders the basic blocks in the function to match the structured order. + void ReorderBasicBlocksInStructuredOrder(); + private: + // Reorders the basic blocks in the function to match the order given by the + // range |{begin,end}|. The range must contain every basic block in the + // function, and no extras. + template + void ReorderBasicBlocks(It begin, It end); + + template + bool ContainsAllBlocksInTheFunction(It begin, It end); + // The OpFunction instruction that begins the definition of this function. std::unique_ptr def_inst_; // All parameters to this function. @@ -262,6 +275,34 @@ inline void Function::AddNonSemanticInstruction( non_semantic_.emplace_back(std::move(non_semantic)); } +template +void Function::ReorderBasicBlocks(It begin, It end) { + // Asserts to make sure every node in the function is in new_order. + assert(ContainsAllBlocksInTheFunction(begin, end)); + + // We have a pointer to all the elements in order, so we can release all + // pointers in |block_|, and then create the new unique pointers from |{begin, + // end}|. + std::for_each(blocks_.begin(), blocks_.end(), + [](std::unique_ptr& bb) { bb.release(); }); + std::transform(begin, end, blocks_.begin(), [](BasicBlock* bb) { + return std::unique_ptr(bb); + }); +} + +template +bool Function::ContainsAllBlocksInTheFunction(It begin, It end) { + std::unordered_multiset range(begin, end); + if (range.size() != blocks_.size()) { + return false; + } + + for (auto& bb : blocks_) { + if (range.count(bb.get()) == 0) return false; + } + return true; +} + } // namespace opt } // namespace spvtools diff --git a/3rdparty/spirv-tools/source/opt/inline_pass.cpp b/3rdparty/spirv-tools/source/opt/inline_pass.cpp index 6e73f1cb9..e14516f75 100644 --- a/3rdparty/spirv-tools/source/opt/inline_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/inline_pass.cpp @@ -794,22 +794,25 @@ bool InlinePass::IsInlinableFunction(Function* func) { return false; } - // Do not inline functions with an OpKill if they are called from a continue - // construct. If it is inlined into a continue construct it will generate - // invalid code. + // Do not inline functions with an abort instruction if they are called from a + // continue construct. If it is inlined into a continue construct the backedge + // will no longer post-dominate the continue target, which is invalid. An + // `OpUnreachable` is acceptable because it will not change post-dominance if + // it is statically unreachable. bool func_is_called_from_continue = funcs_called_from_continue_.count(func->result_id()) != 0; - if (func_is_called_from_continue && ContainsKillOrTerminateInvocation(func)) { + if (func_is_called_from_continue && ContainsAbortOtherThanUnreachable(func)) { return false; } return true; } -bool InlinePass::ContainsKillOrTerminateInvocation(Function* func) const { +bool InlinePass::ContainsAbortOtherThanUnreachable(Function* func) const { return !func->WhileEachInst([](Instruction* inst) { - return !spvOpcodeTerminatesExecution(inst->opcode()); + return inst->opcode() == SpvOpUnreachable || + !spvOpcodeIsAbort(inst->opcode()); }); } diff --git a/3rdparty/spirv-tools/source/opt/inline_pass.h b/3rdparty/spirv-tools/source/opt/inline_pass.h index f20439542..d29c1e074 100644 --- a/3rdparty/spirv-tools/source/opt/inline_pass.h +++ b/3rdparty/spirv-tools/source/opt/inline_pass.h @@ -139,9 +139,9 @@ class InlinePass : public Pass { // Return true if |func| is a function that can be inlined. bool IsInlinableFunction(Function* func); - // Returns true if |func| contains an OpKill or OpTerminateInvocation - // instruction. - bool ContainsKillOrTerminateInvocation(Function* func) const; + // Returns true if |func| contains an abort instruction that is not an + // `OpUnreachable` instruction. + bool ContainsAbortOtherThanUnreachable(Function* func) const; // Update phis in succeeding blocks to point to new last block void UpdateSucceedingPhis( diff --git a/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.cpp b/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.cpp index e2336d360..3318f88f2 100644 --- a/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.cpp @@ -393,6 +393,8 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() { get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst); input_func->SetFunctionEnd(std::move(func_end_inst)); context()->AddFunction(std::move(input_func)); + context()->AddDebug2Inst( + NewGlobalName(search_test_func_id_, "search_and_test")); } return search_test_func_id_; } diff --git a/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h b/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h index a82322395..fb43c397a 100644 --- a/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h +++ b/3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.h @@ -39,7 +39,7 @@ class InstBuffAddrCheckPass : public InstrumentPass { // See optimizer.hpp for pass user documentation. Status Process() override; - const char* name() const override { return "inst-bindless-check-pass"; } + const char* name() const override { return "inst-buff-addr-check-pass"; } private: // Return byte alignment of type |type_id|. Must be int, float, vector, diff --git a/3rdparty/spirv-tools/source/opt/instruction.cpp b/3rdparty/spirv-tools/source/opt/instruction.cpp index 6a8daea31..e775a9926 100644 --- a/3rdparty/spirv-tools/source/opt/instruction.cpp +++ b/3rdparty/spirv-tools/source/opt/instruction.cpp @@ -504,26 +504,6 @@ bool Instruction::IsReadOnlyPointerKernel() const { return storage_class == SpvStorageClassUniformConstant; } -uint32_t Instruction::GetTypeComponent(uint32_t element) const { - uint32_t subtype = 0; - switch (opcode()) { - case SpvOpTypeStruct: - subtype = GetSingleWordInOperand(element); - break; - case SpvOpTypeArray: - case SpvOpTypeRuntimeArray: - case SpvOpTypeVector: - case SpvOpTypeMatrix: - // These types all have uniform subtypes. - subtype = GetSingleWordInOperand(0u); - break; - default: - break; - } - - return subtype; -} - void Instruction::UpdateLexicalScope(uint32_t scope) { dbg_scope_.SetLexicalScope(scope); for (auto& i : dbg_line_insts_) { diff --git a/3rdparty/spirv-tools/source/opt/instruction.h b/3rdparty/spirv-tools/source/opt/instruction.h index 2163d99b3..e79c6289b 100644 --- a/3rdparty/spirv-tools/source/opt/instruction.h +++ b/3rdparty/spirv-tools/source/opt/instruction.h @@ -504,10 +504,6 @@ class Instruction : public utils::IntrusiveNodeBase { // Returns true if this instruction exits this function or aborts execution. bool IsReturnOrAbort() const { return spvOpcodeIsReturnOrAbort(opcode()); } - // Returns the id for the |element|'th subtype. If the |this| is not a - // composite type, this function returns 0. - uint32_t GetTypeComponent(uint32_t element) const; - // Returns true if this instruction is a basic block terminator. bool IsBlockTerminator() const { return spvOpcodeIsBlockTerminator(opcode()); diff --git a/3rdparty/spirv-tools/source/opt/instrument_pass.cpp b/3rdparty/spirv-tools/source/opt/instrument_pass.cpp index ed34fb025..d143d5959 100644 --- a/3rdparty/spirv-tools/source/opt/instrument_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/instrument_pass.cpp @@ -88,6 +88,51 @@ std::unique_ptr InstrumentPass::NewLabel(uint32_t label_id) { return newLabel; } +std::unique_ptr InstrumentPass::NewName( + uint32_t id, const std::string& name_str) { + std::unique_ptr new_name(new Instruction( + context(), SpvOpName, 0, 0, + std::initializer_list{ + {SPV_OPERAND_TYPE_ID, {id}}, + {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}})); + + return new_name; +} + +std::unique_ptr InstrumentPass::NewGlobalName( + uint32_t id, const std::string& name_str) { + std::string prefixed_name; + switch (validation_id_) { + case kInstValidationIdBindless: + prefixed_name = "inst_bindless_"; + break; + case kInstValidationIdBuffAddr: + prefixed_name = "inst_buff_addr_"; + break; + case kInstValidationIdDebugPrintf: + prefixed_name = "inst_printf_"; + break; + default: + assert(false); // add new instrumentation pass here + prefixed_name = "inst_pass_"; + break; + } + prefixed_name += name_str; + return NewName(id, prefixed_name); +} + +std::unique_ptr InstrumentPass::NewMemberName( + uint32_t id, uint32_t member_index, const std::string& name_str) { + std::unique_ptr new_name(new Instruction( + context(), SpvOpMemberName, 0, 0, + std::initializer_list{ + {SPV_OPERAND_TYPE_ID, {id}}, + {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index}}, + {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}})); + + return new_name; +} + uint32_t InstrumentPass::Gen32BitCvtCode(uint32_t val_id, InstructionBuilder* builder) { // Convert integer value to 32-bit if necessary @@ -200,7 +245,9 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx, } break; case SpvExecutionModelGLCompute: case SpvExecutionModelTaskNV: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelTaskEXT: + case SpvExecutionModelMeshEXT: { // Load and store GlobalInvocationId. uint32_t load_id = GenVarLoad( context()->GetBuiltinInputVarId(SpvBuiltInGlobalInvocationId), @@ -525,6 +572,10 @@ uint32_t InstrumentPass::GetOutputBufferId() { {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {SpvStorageClassStorageBuffer}}})); context()->AddGlobalValue(std::move(newVarOp)); + context()->AddDebug2Inst(NewGlobalName(obufTyId, "OutputBuffer")); + context()->AddDebug2Inst(NewMemberName(obufTyId, 0, "written_count")); + context()->AddDebug2Inst(NewMemberName(obufTyId, 1, "data")); + context()->AddDebug2Inst(NewGlobalName(output_buffer_id_, "output_buffer")); deco_mgr->AddDecorationVal(output_buffer_id_, SpvDecorationDescriptorSet, desc_set_); deco_mgr->AddDecorationVal(output_buffer_id_, SpvDecorationBinding, @@ -569,6 +620,9 @@ uint32_t InstrumentPass::GetInputBufferId() { {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {SpvStorageClassStorageBuffer}}})); context()->AddGlobalValue(std::move(newVarOp)); + context()->AddDebug2Inst(NewGlobalName(ibufTyId, "InputBuffer")); + context()->AddDebug2Inst(NewMemberName(ibufTyId, 0, "data")); + context()->AddDebug2Inst(NewGlobalName(input_buffer_id_, "input_buffer")); deco_mgr->AddDecorationVal(input_buffer_id_, SpvDecorationDescriptorSet, desc_set_); deco_mgr->AddDecorationVal(input_buffer_id_, SpvDecorationBinding, @@ -783,6 +837,12 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx, get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst); output_func->SetFunctionEnd(std::move(func_end_inst)); context()->AddFunction(std::move(output_func)); + + std::string name("stream_write_"); + name += std::to_string(param_cnt); + + context()->AddDebug2Inst( + NewGlobalName(param2output_func_id_[param_cnt], name)); } return param2output_func_id_[param_cnt]; } @@ -863,6 +923,11 @@ uint32_t InstrumentPass::GetDirectReadFunctionId(uint32_t param_cnt) { get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst); input_func->SetFunctionEnd(std::move(func_end_inst)); context()->AddFunction(std::move(input_func)); + + std::string name("direct_read_"); + name += std::to_string(param_cnt); + context()->AddDebug2Inst(NewGlobalName(func_id, name)); + param2input_func_id_[param_cnt] = func_id; return func_id; } @@ -1001,7 +1066,8 @@ bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) { stage != SpvExecutionModelAnyHitNV && stage != SpvExecutionModelClosestHitNV && stage != SpvExecutionModelMissNV && - stage != SpvExecutionModelCallableNV) { + stage != SpvExecutionModelCallableNV && + stage != SpvExecutionModelTaskEXT && stage != SpvExecutionModelMeshEXT) { if (consumer()) { std::string message = "Stage not supported by instrumentation"; consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str()); diff --git a/3rdparty/spirv-tools/source/opt/instrument_pass.h b/3rdparty/spirv-tools/source/opt/instrument_pass.h index 90c1dd47e..215b02635 100644 --- a/3rdparty/spirv-tools/source/opt/instrument_pass.h +++ b/3rdparty/spirv-tools/source/opt/instrument_pass.h @@ -224,6 +224,19 @@ class InstrumentPass : public Pass { // Return new label. std::unique_ptr NewLabel(uint32_t label_id); + // Set the name function parameter or local variable + std::unique_ptr NewName(uint32_t id, + const std::string& name_str); + + // Set the name for a function or global variable, names will be + // prefixed to identify which instrumentation pass generated them. + std::unique_ptr NewGlobalName(uint32_t id, + const std::string& name_str); + + // Set the name for a structure member + std::unique_ptr NewMemberName(uint32_t id, uint32_t member_index, + const std::string& name_str); + // Return id for 32-bit unsigned type uint32_t GetUintId(); 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 9491798e4..d11682f34 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 @@ -188,7 +188,9 @@ bool LocalAccessChainConvertPass::Is32BitConstantIndexAccessChain( if (opInst->opcode() != SpvOpConstant) return false; const auto* index = context()->get_constant_mgr()->GetConstantFromInst(opInst); - if (index->GetSignExtendedValue() > UINT32_MAX) return false; + int64_t index_value = index->GetSignExtendedValue(); + if (index_value > UINT32_MAX) return false; + if (index_value < 0) return false; } ++inIdx; return true; diff --git a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.h b/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.h index eabf8645b..c3731b1c9 100644 --- a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.h +++ b/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.h @@ -94,8 +94,8 @@ class LocalAccessChainConvertPass : public MemPass { bool ReplaceAccessChainLoad(const Instruction* address_inst, Instruction* original_load); - // Return true if all indices of access chain |acp| are OpConstant integers - // whose values can fit into an unsigned 32-bit value. + // Return true if all indices of the access chain |acp| are OpConstant + // integers whose signed values can be represented as unsigned 32-bit values. bool Is32BitConstantIndexAccessChain(const Instruction* acp) const; // Identify all function scope variables of target type which are 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 8cdd0abdc..81648c7ba 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 @@ -175,29 +175,9 @@ bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) { bool LocalSingleStoreElimPass::RewriteDebugDeclares(Instruction* store_inst, uint32_t var_id) { - std::unordered_set invisible_decls; uint32_t value_id = store_inst->GetSingleWordInOperand(1); - bool modified = - context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible( - store_inst, var_id, value_id, store_inst, &invisible_decls); - - // For cases like the argument passing for an inlined function, the value - // assignment is out of DebugDeclare's scope, but we have to preserve the - // value assignment information using DebugValue. Generally, we need - // ssa-rewrite analysis to decide a proper value assignment but at this point - // we confirm that |var_id| has a single store. We can safely add DebugValue. - if (!invisible_decls.empty()) { - BasicBlock* store_block = context()->get_instr_block(store_inst); - DominatorAnalysis* dominator_analysis = - context()->GetDominatorAnalysis(store_block->GetParent()); - for (auto* decl : invisible_decls) { - if (dominator_analysis->Dominates(store_inst, decl)) { - context()->get_debug_info_mgr()->AddDebugValueForDecl(decl, value_id, - decl, store_inst); - modified = true; - } - } - } + bool modified = context()->get_debug_info_mgr()->AddDebugValueForVariable( + store_inst, var_id, value_id, store_inst); modified |= context()->get_debug_info_mgr()->KillDebugDeclares(var_id); return modified; } diff --git a/3rdparty/spirv-tools/source/opt/pass_manager.cpp b/3rdparty/spirv-tools/source/opt/pass_manager.cpp index a73ff7cf4..d3c47e7f3 100644 --- a/3rdparty/spirv-tools/source/opt/pass_manager.cpp +++ b/3rdparty/spirv-tools/source/opt/pass_manager.cpp @@ -39,7 +39,7 @@ Pass::Status PassManager::Run(IRContext* context) { t.SetMessageConsumer(consumer()); std::string disassembly; std::string pass_name = (pass ? pass->name() : ""); - if (!t.Disassemble(binary, &disassembly, 0)) { + if (!t.Disassemble(binary, &disassembly)) { std::string msg = "Disassembly failed before pass "; msg += pass_name + "\n"; spv_position_t null_pos{0, 0, 0}; diff --git a/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp b/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp index 29ab6123f..22d811044 100644 --- a/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp @@ -67,7 +67,6 @@ namespace opt { namespace { const uint32_t kStoreValIdInIdx = 1; const uint32_t kVariableInitIdInIdx = 1; -const uint32_t kDebugDeclareOperandVariableIdx = 5; } // namespace std::string SSARewriter::PhiCandidate::PrettyPrint(const CFG* cfg) const { @@ -315,8 +314,8 @@ void SSARewriter::ProcessStore(Instruction* inst, BasicBlock* bb) { } if (pass_->IsTargetVar(var_id)) { WriteVariable(var_id, bb, val_id); - pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible( - inst, var_id, val_id, inst, &decls_invisible_to_value_assignment_); + pass_->context()->get_debug_info_mgr()->AddDebugValueForVariable( + inst, var_id, val_id, inst); #if SSA_REWRITE_DEBUGGING_LEVEL > 1 std::cerr << "\tFound store '%" << var_id << " = %" << val_id << "': " @@ -559,9 +558,9 @@ bool SSARewriter::ApplyReplacements() { // Add DebugValue for the new OpPhi instruction. insert_it->SetDebugScope(local_var->GetDebugScope()); - pass_->context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible( + pass_->context()->get_debug_info_mgr()->AddDebugValueForVariable( &*insert_it, phi_candidate->var_id(), phi_candidate->result_id(), - &*insert_it, &decls_invisible_to_value_assignment_); + &*insert_it); modified = true; } @@ -650,62 +649,6 @@ void SSARewriter::FinalizePhiCandidates() { } } -Pass::Status SSARewriter::AddDebugValuesForInvisibleDebugDecls(Function* fp) { - // For the cases the value assignment is invisible to DebugDeclare e.g., - // the argument passing for an inlined function. - // - // Before inlining foo(int x): - // a = 3; - // foo(3); - // After inlining: - // a = 3; - // foo and x disappeared but we want to specify "DebugValue: %x = %int_3". - // - // We want to specify the value for the variable using |defs_at_block_[bb]|, - // where |bb| is the basic block contains the decl. - DominatorAnalysis* dom_tree = pass_->context()->GetDominatorAnalysis(fp); - Pass::Status status = Pass::Status::SuccessWithoutChange; - for (auto* decl : decls_invisible_to_value_assignment_) { - uint32_t var_id = - decl->GetSingleWordOperand(kDebugDeclareOperandVariableIdx); - auto* var = pass_->get_def_use_mgr()->GetDef(var_id); - if (var->opcode() == SpvOpFunctionParameter) continue; - - auto* bb = pass_->context()->get_instr_block(decl); - uint32_t value_id = GetValueAtBlock(var_id, bb); - Instruction* value = nullptr; - if (value_id) value = pass_->get_def_use_mgr()->GetDef(value_id); - - // If |value| is defined before the function body, it dominates |decl|. - // If |value| dominates |decl|, we can set it as DebugValue. - if (value && (pass_->context()->get_instr_block(value) == nullptr || - dom_tree->Dominates(value, decl))) { - if (pass_->context()->get_debug_info_mgr()->AddDebugValueForDecl( - decl, value->result_id(), decl, value) == nullptr) { - return Pass::Status::Failure; - } - } else { - // If |value| in the same basic block does not dominate |decl|, we can - // assign the value in the immediate dominator. - value_id = GetValueAtBlock(var_id, dom_tree->ImmediateDominator(bb)); - if (value_id) value = pass_->get_def_use_mgr()->GetDef(value_id); - if (value_id && - pass_->context()->get_debug_info_mgr()->AddDebugValueForDecl( - decl, value_id, decl, value) == nullptr) { - return Pass::Status::Failure; - } - } - - // DebugDeclares of target variables will be removed by - // SSARewritePass::Process(). - if (!pass_->IsTargetVar(var_id)) { - pass_->context()->get_debug_info_mgr()->KillDebugDeclares(var_id); - } - status = Pass::Status::SuccessWithChange; - } - return status; -} - Pass::Status SSARewriter::RewriteFunctionIntoSSA(Function* fp) { #if SSA_REWRITE_DEBUGGING_LEVEL > 0 std::cerr << "Function before SSA rewrite:\n" @@ -735,12 +678,6 @@ Pass::Status SSARewriter::RewriteFunctionIntoSSA(Function* fp) { // Finally, apply all the replacements in the IR. bool modified = ApplyReplacements(); - auto status = AddDebugValuesForInvisibleDebugDecls(fp); - if (status == Pass::Status::SuccessWithChange || - status == Pass::Status::Failure) { - return status; - } - #if SSA_REWRITE_DEBUGGING_LEVEL > 0 std::cerr << "\n\n\nFunction after SSA rewrite:\n" << fp->PrettyPrint(0) << "\n"; diff --git a/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.h b/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.h index 1f4cd24ca..2470f85f6 100644 --- a/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.h +++ b/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.h @@ -253,11 +253,6 @@ class SSARewriter { // candidates. void FinalizePhiCandidates(); - // Adds DebugValues for DebugDeclares in - // |decls_invisible_to_value_assignment_|. Returns whether the function was - // modified or not, and whether or not the conversion was successful. - Pass::Status AddDebugValuesForInvisibleDebugDecls(Function* fp); - // Prints the table of Phi candidates to std::cerr. void PrintPhiCandidates() const; @@ -295,10 +290,6 @@ class SSARewriter { // Memory pass requesting the SSA rewriter. MemPass* pass_; - - // Set of DebugDeclare instructions that are not added as DebugValue because - // they are invisible to the store or phi instructions. - std::unordered_set decls_invisible_to_value_assignment_; }; class SSARewritePass : public MemPass { diff --git a/3rdparty/spirv-tools/source/print.cpp b/3rdparty/spirv-tools/source/print.cpp index 2418c5bc9..6c94e2b7f 100644 --- a/3rdparty/spirv-tools/source/print.cpp +++ b/3rdparty/spirv-tools/source/print.cpp @@ -16,7 +16,8 @@ #if defined(SPIRV_ANDROID) || defined(SPIRV_LINUX) || defined(SPIRV_MAC) || \ defined(SPIRV_IOS) || defined(SPIRV_TVOS) || defined(SPIRV_FREEBSD) || \ - defined(SPIRV_EMSCRIPTEN) || defined(SPIRV_FUCHSIA) + defined(SPIRV_OPENBSD) || defined(SPIRV_EMSCRIPTEN) || \ + defined(SPIRV_FUCHSIA) || defined(SPIRV_GNU) namespace spvtools { clr::reset::operator const char*() { return "\x1b[0m"; } diff --git a/3rdparty/spirv-tools/source/spirv_validator_options.cpp b/3rdparty/spirv-tools/source/spirv_validator_options.cpp index e5b1eece0..b72a64460 100644 --- a/3rdparty/spirv-tools/source/spirv_validator_options.cpp +++ b/3rdparty/spirv-tools/source/spirv_validator_options.cpp @@ -125,3 +125,8 @@ void spvValidatorOptionsSetAllowLocalSizeId(spv_validator_options options, bool val) { options->allow_localsizeid = val; } + +void spvValidatorOptionsSetFriendlyNames(spv_validator_options options, + bool val) { + options->use_friendly_names = val; +} diff --git a/3rdparty/spirv-tools/source/spirv_validator_options.h b/3rdparty/spirv-tools/source/spirv_validator_options.h index a357c031b..01450480c 100644 --- a/3rdparty/spirv-tools/source/spirv_validator_options.h +++ b/3rdparty/spirv-tools/source/spirv_validator_options.h @@ -48,7 +48,8 @@ struct spv_validator_options_t { workgroup_scalar_block_layout(false), skip_block_layout(false), allow_localsizeid(false), - before_hlsl_legalization(false) {} + before_hlsl_legalization(false), + use_friendly_names(true) {} validator_universal_limits_t universal_limits_; bool relax_struct_store; @@ -60,6 +61,7 @@ struct spv_validator_options_t { bool skip_block_layout; bool allow_localsizeid; bool before_hlsl_legalization; + bool use_friendly_names; }; #endif // SOURCE_SPIRV_VALIDATOR_OPTIONS_H_ diff --git a/3rdparty/spirv-tools/source/val/validate.cpp b/3rdparty/spirv-tools/source/val/validate.cpp index 55e9fd2b4..efb9225e6 100644 --- a/3rdparty/spirv-tools/source/val/validate.cpp +++ b/3rdparty/spirv-tools/source/val/validate.cpp @@ -209,6 +209,8 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( return error; } + bool has_mask_task_nv = false; + bool has_mask_task_ext = false; std::vector visited_entry_points; for (auto& instruction : vstate->ordered_instructions()) { { @@ -247,6 +249,11 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( } } visited_entry_points.push_back(inst); + + has_mask_task_nv |= (execution_model == SpvExecutionModelTaskNV || + execution_model == SpvExecutionModelMeshNV); + has_mask_task_ext |= (execution_model == SpvExecutionModelTaskEXT || + execution_model == SpvExecutionModelMeshEXT); } if (inst->opcode() == SpvOpFunctionCall) { if (!vstate->in_function_body()) { @@ -298,6 +305,12 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr) << "Missing required OpSamplerImageAddressingModeNV instruction."; + if (has_mask_task_ext && has_mask_task_nv) + return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr) + << vstate->VkErrorID(7102) + << "Module can't mix MeshEXT/TaskEXT with MeshNV/TaskNV Execution " + "Model."; + // Catch undefined forward references before performing further checks. if (auto error = ValidateForwardDecls(*vstate)) return error; @@ -351,6 +364,8 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( if (auto error = LiteralsPass(*vstate, &instruction)) return error; if (auto error = RayQueryPass(*vstate, &instruction)) return error; + if (auto error = RayTracingPass(*vstate, &instruction)) return error; + if (auto error = MeshShadingPass(*vstate, &instruction)) return error; } // Validate the preconditions involving adjacent instructions. e.g. SpvOpPhi diff --git a/3rdparty/spirv-tools/source/val/validate.h b/3rdparty/spirv-tools/source/val/validate.h index 97d4683e0..4b953ba31 100644 --- a/3rdparty/spirv-tools/source/val/validate.h +++ b/3rdparty/spirv-tools/source/val/validate.h @@ -200,6 +200,12 @@ spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst); /// Validates correctness of ray query instructions. spv_result_t RayQueryPass(ValidationState_t& _, const Instruction* inst); +/// Validates correctness of ray tracing instructions. +spv_result_t RayTracingPass(ValidationState_t& _, const Instruction* inst); + +/// Validates correctness of mesh shading instructions. +spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst); + /// Calculates the reachability of basic blocks. void ReachabilityPass(ValidationState_t& _); diff --git a/3rdparty/spirv-tools/source/val/validate_annotation.cpp b/3rdparty/spirv-tools/source/val/validate_annotation.cpp index c27c79943..21f999b09 100644 --- a/3rdparty/spirv-tools/source/val/validate_annotation.cpp +++ b/3rdparty/spirv-tools/source/val/validate_annotation.cpp @@ -22,138 +22,6 @@ namespace spvtools { namespace val { namespace { -std::string LogStringForDecoration(uint32_t decoration) { - switch (decoration) { - case SpvDecorationRelaxedPrecision: - return "RelaxedPrecision"; - case SpvDecorationSpecId: - return "SpecId"; - case SpvDecorationBlock: - return "Block"; - case SpvDecorationBufferBlock: - return "BufferBlock"; - case SpvDecorationRowMajor: - return "RowMajor"; - case SpvDecorationColMajor: - return "ColMajor"; - case SpvDecorationArrayStride: - return "ArrayStride"; - case SpvDecorationMatrixStride: - return "MatrixStride"; - case SpvDecorationGLSLShared: - return "GLSLShared"; - case SpvDecorationGLSLPacked: - return "GLSLPacked"; - case SpvDecorationCPacked: - return "CPacked"; - case SpvDecorationBuiltIn: - return "BuiltIn"; - case SpvDecorationNoPerspective: - return "NoPerspective"; - case SpvDecorationFlat: - return "Flat"; - case SpvDecorationPatch: - return "Patch"; - case SpvDecorationCentroid: - return "Centroid"; - case SpvDecorationSample: - return "Sample"; - case SpvDecorationInvariant: - return "Invariant"; - case SpvDecorationRestrict: - return "Restrict"; - case SpvDecorationAliased: - return "Aliased"; - case SpvDecorationVolatile: - return "Volatile"; - case SpvDecorationConstant: - return "Constant"; - case SpvDecorationCoherent: - return "Coherent"; - case SpvDecorationNonWritable: - return "NonWritable"; - case SpvDecorationNonReadable: - return "NonReadable"; - case SpvDecorationUniform: - return "Uniform"; - case SpvDecorationSaturatedConversion: - return "SaturatedConversion"; - case SpvDecorationStream: - return "Stream"; - case SpvDecorationLocation: - return "Location"; - case SpvDecorationComponent: - return "Component"; - case SpvDecorationIndex: - return "Index"; - case SpvDecorationBinding: - return "Binding"; - case SpvDecorationDescriptorSet: - return "DescriptorSet"; - case SpvDecorationOffset: - return "Offset"; - case SpvDecorationXfbBuffer: - return "XfbBuffer"; - case SpvDecorationXfbStride: - return "XfbStride"; - case SpvDecorationFuncParamAttr: - return "FuncParamAttr"; - case SpvDecorationFPRoundingMode: - return "FPRoundingMode"; - case SpvDecorationFPFastMathMode: - return "FPFastMathMode"; - case SpvDecorationLinkageAttributes: - return "LinkageAttributes"; - case SpvDecorationNoContraction: - return "NoContraction"; - case SpvDecorationInputAttachmentIndex: - return "InputAttachmentIndex"; - case SpvDecorationAlignment: - return "Alignment"; - case SpvDecorationMaxByteOffset: - return "MaxByteOffset"; - case SpvDecorationAlignmentId: - return "AlignmentId"; - case SpvDecorationMaxByteOffsetId: - return "MaxByteOffsetId"; - case SpvDecorationNoSignedWrap: - return "NoSignedWrap"; - case SpvDecorationNoUnsignedWrap: - return "NoUnsignedWrap"; - case SpvDecorationExplicitInterpAMD: - return "ExplicitInterpAMD"; - case SpvDecorationOverrideCoverageNV: - return "OverrideCoverageNV"; - case SpvDecorationPassthroughNV: - return "PassthroughNV"; - case SpvDecorationViewportRelativeNV: - return "ViewportRelativeNV"; - case SpvDecorationSecondaryViewportRelativeNV: - return "SecondaryViewportRelativeNV"; - case SpvDecorationPerPrimitiveNV: - return "PerPrimitiveNV"; - case SpvDecorationPerViewNV: - return "PerViewNV"; - case SpvDecorationPerTaskNV: - return "PerTaskNV"; - case SpvDecorationPerVertexKHR: - return "PerVertexKHR"; - case SpvDecorationNonUniform: - return "NonUniform"; - case SpvDecorationRestrictPointer: - return "RestrictPointer"; - case SpvDecorationAliasedPointer: - return "AliasedPointer"; - case SpvDecorationCounterBuffer: - return "CounterBuffer"; - case SpvDecorationHlslSemanticGOOGLE: - return "HlslSemanticGOOGLE"; - default: - break; - } - return "Unknown"; -} - // Returns true if the decoration takes ID parameters. // TODO(dneto): This can be generated from the grammar. bool DecorationTakesIdParameters(SpvDecoration type) { @@ -233,8 +101,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec, auto fail = [&_, dec, inst, target](uint32_t vuid) -> DiagnosticStream { DiagnosticStream ds = std::move( _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(vuid) << LogStringForDecoration(dec) - << " decoration on target '" << _.getIdName(target->id()) << "' "); + << _.VkErrorID(vuid) << _.SpvDecorationString(dec) + << " decoration on target " << _.getIdName(target->id()) << " "); return ds; }; switch (dec) { @@ -334,7 +202,7 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec, sc != SpvStorageClassIncomingCallableDataKHR && sc != SpvStorageClassShaderRecordBufferKHR) { return _.diag(SPV_ERROR_INVALID_ID, target) - << _.VkErrorID(6672) << LogStringForDecoration(dec) + << _.VkErrorID(6672) << _.SpvDecorationString(dec) << " decoration must not be applied to this storage class"; } break; @@ -391,7 +259,7 @@ spv_result_t ValidateDecorate(ValidationState_t& _, const Instruction* inst) { (decoration == SpvDecorationGLSLPacked)) { return _.diag(SPV_ERROR_INVALID_ID, inst) << _.VkErrorID(4669) << "OpDecorate decoration '" - << LogStringForDecoration(decoration) + << _.SpvDecorationString(decoration) << "' is not valid for the Vulkan execution environment."; } } @@ -405,7 +273,7 @@ spv_result_t ValidateDecorate(ValidationState_t& _, const Instruction* inst) { if (target->opcode() != SpvOpDecorationGroup) { if (IsMemberDecorationOnly(decoration)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << LogStringForDecoration(decoration) + << _.SpvDecorationString(decoration) << " can only be applied to structure members"; } @@ -440,8 +308,8 @@ spv_result_t ValidateMemberDecorate(ValidationState_t& _, const auto struct_type = _.FindDef(struct_type_id); if (!struct_type || SpvOpTypeStruct != struct_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpMemberDecorate Structure type '" - << _.getIdName(struct_type_id) << "' is not a struct type."; + << "OpMemberDecorate Structure type " + << _.getIdName(struct_type_id) << " is not a struct type."; } const auto member = inst->GetOperandAs(1); const auto member_count = @@ -458,7 +326,7 @@ spv_result_t ValidateMemberDecorate(ValidationState_t& _, const auto decoration = inst->GetOperandAs(2); if (IsNotMemberDecoration(decoration)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << LogStringForDecoration(decoration) + << _.SpvDecorationString(decoration) << " cannot be applied to structure members"; } @@ -490,17 +358,16 @@ spv_result_t ValidateGroupDecorate(ValidationState_t& _, auto decoration_group = _.FindDef(decoration_group_id); if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpGroupDecorate Decoration group '" - << _.getIdName(decoration_group_id) - << "' is not a decoration group."; + << "OpGroupDecorate Decoration group " + << _.getIdName(decoration_group_id) << " is not a decoration group."; } for (unsigned i = 1; i < inst->operands().size(); ++i) { auto target_id = inst->GetOperandAs(i); auto target = _.FindDef(target_id); if (!target || target->opcode() == SpvOpDecorationGroup) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpGroupDecorate may not target OpDecorationGroup '" - << _.getIdName(target_id) << "'"; + << "OpGroupDecorate may not target OpDecorationGroup " + << _.getIdName(target_id); } } return SPV_SUCCESS; @@ -512,9 +379,8 @@ spv_result_t ValidateGroupMemberDecorate(ValidationState_t& _, const auto decoration_group = _.FindDef(decoration_group_id); if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpGroupMemberDecorate Decoration group '" - << _.getIdName(decoration_group_id) - << "' is not a decoration group."; + << "OpGroupMemberDecorate Decoration group " + << _.getIdName(decoration_group_id) << " is not a decoration group."; } // Grammar checks ensures that the number of arguments to this instruction // is an odd number: 1 decoration group + (id,literal) pairs. @@ -524,8 +390,8 @@ spv_result_t ValidateGroupMemberDecorate(ValidationState_t& _, auto struct_instr = _.FindDef(struct_id); if (!struct_instr || SpvOpTypeStruct != struct_instr->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpGroupMemberDecorate Structure type '" - << _.getIdName(struct_id) << "' is not a struct type."; + << "OpGroupMemberDecorate Structure type " + << _.getIdName(struct_id) << " is not a struct type."; } const uint32_t num_struct_members = static_cast(struct_instr->words().size() - 2); diff --git a/3rdparty/spirv-tools/source/val/validate_atomics.cpp b/3rdparty/spirv-tools/source/val/validate_atomics.cpp index 3b0a7fa8e..bf565c310 100644 --- a/3rdparty/spirv-tools/source/val/validate_atomics.cpp +++ b/3rdparty/spirv-tools/source/val/validate_atomics.cpp @@ -40,6 +40,7 @@ bool IsStorageClassAllowedByUniversalRules(uint32_t storage_class) { case SpvStorageClassImage: case SpvStorageClassFunction: case SpvStorageClassPhysicalStorageBuffer: + case SpvStorageClassTaskPayloadWorkgroupEXT: return true; break; default: @@ -206,12 +207,13 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) { (storage_class != SpvStorageClassStorageBuffer) && (storage_class != SpvStorageClassWorkgroup) && (storage_class != SpvStorageClassImage) && - (storage_class != SpvStorageClassPhysicalStorageBuffer)) { + (storage_class != SpvStorageClassPhysicalStorageBuffer) && + (storage_class != SpvStorageClassTaskPayloadWorkgroupEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << _.VkErrorID(4686) << spvOpcodeString(opcode) << ": Vulkan spec only allows storage classes for atomic to " - "be: Uniform, Workgroup, Image, StorageBuffer, or " - "PhysicalStorageBuffer."; + "be: Uniform, Workgroup, Image, StorageBuffer, " + "PhysicalStorageBuffer or TaskPayloadWorkgroupEXT."; } } else if (storage_class == SpvStorageClassFunction) { return _.diag(SPV_ERROR_INVALID_DATA, inst) diff --git a/3rdparty/spirv-tools/source/val/validate_barriers.cpp b/3rdparty/spirv-tools/source/val/validate_barriers.cpp index 3a9e3e7c5..03225d86a 100644 --- a/3rdparty/spirv-tools/source/val/validate_barriers.cpp +++ b/3rdparty/spirv-tools/source/val/validate_barriers.cpp @@ -50,7 +50,8 @@ spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) { *message = "OpControlBarrier requires one of the following " "Execution " - "Models: TessellationControl, GLCompute or Kernel"; + "Models: TessellationControl, GLCompute, Kernel, " + "MeshNV or TaskNV"; } return false; } diff --git a/3rdparty/spirv-tools/source/val/validate_builtins.cpp b/3rdparty/spirv-tools/source/val/validate_builtins.cpp index 379705ac0..d5b89eb1a 100644 --- a/3rdparty/spirv-tools/source/val/validate_builtins.cpp +++ b/3rdparty/spirv-tools/source/val/validate_builtins.cpp @@ -1179,9 +1179,16 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference( &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be " "used for variables with Input storage class if execution model is " - "Vertex.", + "MeshNV.", SpvExecutionModelMeshNV, decoration, built_in_inst, referenced_from_inst, std::placeholders::_1)); + id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( + &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, + "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be " + "used for variables with Input storage class if execution model is " + "MeshEXT.", + SpvExecutionModelMeshEXT, decoration, built_in_inst, + referenced_from_inst, std::placeholders::_1)); } if (storage_class == SpvStorageClassOutput) { @@ -1224,7 +1231,8 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference( case SpvExecutionModelTessellationControl: case SpvExecutionModelTessellationEvaluation: case SpvExecutionModelGeometry: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: { if (decoration.struct_member_index() != Decoration::kInvalidMember) { // The outer level of array is applied on the variable. if (spv_result_t error = ValidateF32Arr( @@ -1856,7 +1864,8 @@ spv_result_t BuiltInsValidator::ValidatePointSizeAtReference( case SpvExecutionModelTessellationControl: case SpvExecutionModelTessellationEvaluation: case SpvExecutionModelGeometry: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: { // PointSize can be a per-vertex variable for tessellation control, // tessellation evaluation and geometry shader stages. In such cases // variables will have an array of 32-bit floats. @@ -1957,6 +1966,13 @@ spv_result_t BuiltInsValidator::ValidatePositionAtReference( "with Input storage class if execution model is MeshNV.", SpvExecutionModelMeshNV, decoration, built_in_inst, referenced_from_inst, std::placeholders::_1)); + id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( + &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319, + "Vulkan spec doesn't allow BuiltIn Position to be used " + "for variables " + "with Input storage class if execution model is MeshEXT.", + SpvExecutionModelMeshEXT, decoration, built_in_inst, + referenced_from_inst, std::placeholders::_1)); } for (const SpvExecutionModel execution_model : execution_models_) { @@ -1980,7 +1996,8 @@ spv_result_t BuiltInsValidator::ValidatePositionAtReference( case SpvExecutionModelGeometry: case SpvExecutionModelTessellationControl: case SpvExecutionModelTessellationEvaluation: - case SpvExecutionModelMeshNV: { + case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: { // Position can be a per-vertex variable for tessellation control, // tessellation evaluation, geometry and mesh shader stages. In such // cases variables will have an array of 4-component 32-bit float @@ -2151,6 +2168,7 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveIdAtReference( case SpvExecutionModelTessellationEvaluation: case SpvExecutionModelGeometry: case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: case SpvExecutionModelIntersectionKHR: case SpvExecutionModelAnyHitKHR: case SpvExecutionModelClosestHitKHR: { @@ -2163,9 +2181,8 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveIdAtReference( << _.VkErrorID(4330) << "Vulkan spec allows BuiltIn PrimitiveId to be used only " "with Fragment, TessellationControl, " - "TessellationEvaluation, Geometry, MeshNV, " - "IntersectionKHR, " - "AnyHitKHR, and ClosestHitKHR execution models. " + "TessellationEvaluation, Geometry, MeshNV, MeshEXT, " + "IntersectionKHR, AnyHitKHR, and ClosestHitKHR execution models. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -2713,7 +2730,8 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( assert(function_id_ == 0); for (const auto em : {SpvExecutionModelVertex, SpvExecutionModelTessellationEvaluation, - SpvExecutionModelGeometry, SpvExecutionModelMeshNV}) { + SpvExecutionModelGeometry, SpvExecutionModelMeshNV, + SpvExecutionModelMeshEXT}) { id_to_at_reference_checks_[referenced_from_inst.id()].push_back( std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, ((operand == SpvBuiltInLayer) ? 4274 : 4406), @@ -2721,7 +2739,7 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( "ViewportIndex to be " "used for variables with Input storage class if " "execution model is Vertex, TessellationEvaluation, " - "Geometry, or MeshNV.", + "Geometry, MeshNV or MeshEXT.", em, decoration, built_in_inst, referenced_from_inst, std::placeholders::_1)); } @@ -2746,6 +2764,7 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( case SpvExecutionModelGeometry: case SpvExecutionModelFragment: case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: // Ok. break; case SpvExecutionModelVertex: @@ -2925,7 +2944,10 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference( for (const SpvExecutionModel execution_model : execution_models_) { bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute || execution_model == SpvExecutionModelTaskNV || - execution_model == SpvExecutionModelMeshNV; + execution_model == SpvExecutionModelMeshNV || + execution_model == SpvExecutionModelTaskEXT || + execution_model == SpvExecutionModelMeshEXT; + if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) { uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel); return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) @@ -2933,7 +2955,8 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference( << spvLogStringForEnv(_.context()->target_env) << " spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin) - << " to be used only with GLCompute, MeshNV, or TaskNV execution model. " + << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or" + << " TaskEXT execution model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -3007,7 +3030,9 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference( for (const SpvExecutionModel execution_model : execution_models_) { bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute || execution_model == SpvExecutionModelTaskNV || - execution_model == SpvExecutionModelMeshNV; + execution_model == SpvExecutionModelMeshNV || + execution_model == SpvExecutionModelTaskEXT || + execution_model == SpvExecutionModelMeshEXT; if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) { uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel); return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) @@ -3015,7 +3040,8 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference( << spvLogStringForEnv(_.context()->target_env) << " spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin) - << " to be used only with GLCompute, MeshNV, or TaskNV execution model. " + << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or " + << "TaskEXT execution model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -3159,14 +3185,17 @@ spv_result_t BuiltInsValidator::ValidateWorkgroupSizeAtReference( for (const SpvExecutionModel execution_model : execution_models_) { if (execution_model != SpvExecutionModelGLCompute && execution_model != SpvExecutionModelTaskNV && - execution_model != SpvExecutionModelMeshNV) { + execution_model != SpvExecutionModelMeshNV && + execution_model != SpvExecutionModelTaskEXT && + execution_model != SpvExecutionModelMeshEXT) { return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) << _.VkErrorID(4425) << spvLogStringForEnv(_.context()->target_env) << " spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]) - << " to be used only with GLCompute, MeshNV, or TaskNV execution model. " + << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or " + << "TaskEXT execution model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); } @@ -3297,12 +3326,15 @@ spv_result_t BuiltInsValidator::ValidateDrawIndexAtReference( for (const SpvExecutionModel execution_model : execution_models_) { if (execution_model != SpvExecutionModelVertex && execution_model != SpvExecutionModelMeshNV && - execution_model != SpvExecutionModelTaskNV) { + execution_model != SpvExecutionModelTaskNV && + execution_model != SpvExecutionModelMeshEXT && + execution_model != SpvExecutionModelTaskEXT) { return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) << _.VkErrorID(4207) << "Vulkan spec allows BuiltIn " << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, operand) - << " to be used only with Vertex, MeshNV, or TaskNV execution " + << " to be used only with Vertex, MeshNV, TaskNV , MeshEXT or" + << " TaskEXT execution " "model. " << GetReferenceDesc(decoration, built_in_inst, referenced_inst, referenced_from_inst, execution_model); @@ -3818,6 +3850,7 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtReference( case SpvExecutionModelVertex: case SpvExecutionModelGeometry: case SpvExecutionModelMeshNV: + case SpvExecutionModelMeshEXT: break; default: { return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) @@ -4247,44 +4280,15 @@ spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition( case SpvBuiltInCullMaskKHR: { return ValidateRayTracingBuiltinsAtDefinition(decoration, inst); } - case SpvBuiltInWorkDim: - case SpvBuiltInGlobalSize: - case SpvBuiltInEnqueuedWorkgroupSize: - case SpvBuiltInGlobalOffset: - case SpvBuiltInGlobalLinearId: - case SpvBuiltInSubgroupMaxSize: - case SpvBuiltInNumEnqueuedSubgroups: - case SpvBuiltInBaryCoordNoPerspAMD: - case SpvBuiltInBaryCoordNoPerspCentroidAMD: - case SpvBuiltInBaryCoordNoPerspSampleAMD: - case SpvBuiltInBaryCoordSmoothAMD: - case SpvBuiltInBaryCoordSmoothCentroidAMD: - case SpvBuiltInBaryCoordSmoothSampleAMD: - case SpvBuiltInBaryCoordPullModelAMD: - case SpvBuiltInViewportMaskNV: - case SpvBuiltInSecondaryPositionNV: - case SpvBuiltInSecondaryViewportMaskNV: - case SpvBuiltInPositionPerViewNV: - case SpvBuiltInViewportMaskPerViewNV: - case SpvBuiltInMax: - case SpvBuiltInTaskCountNV: - case SpvBuiltInPrimitiveCountNV: - case SpvBuiltInPrimitiveIndicesNV: - case SpvBuiltInClipDistancePerViewNV: - case SpvBuiltInCullDistancePerViewNV: - case SpvBuiltInLayerPerViewNV: - case SpvBuiltInMeshViewCountNV: - case SpvBuiltInMeshViewIndicesNV: - case SpvBuiltInCurrentRayTimeNV: - // No validation rules (for the moment). - break; - case SpvBuiltInPrimitiveShadingRateKHR: { return ValidatePrimitiveShadingRateAtDefinition(decoration, inst); } case SpvBuiltInShadingRateKHR: { return ValidateShadingRateAtDefinition(decoration, inst); } + default: + // No validation rules (for the moment). + break; } return SPV_SUCCESS; } diff --git a/3rdparty/spirv-tools/source/val/validate_cfg.cpp b/3rdparty/spirv-tools/source/val/validate_cfg.cpp index 0220fcd33..cc0b999f2 100644 --- a/3rdparty/spirv-tools/source/val/validate_cfg.cpp +++ b/3rdparty/spirv-tools/source/val/validate_cfg.cpp @@ -239,23 +239,23 @@ spv_result_t ValidateReturnValue(ValidationState_t& _, const auto value = _.FindDef(value_id); if (!value || !value->type_id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpReturnValue Value '" << _.getIdName(value_id) - << "' does not represent a value."; + << "OpReturnValue Value " << _.getIdName(value_id) + << " does not represent a value."; } auto value_type = _.FindDef(value->type_id()); if (!value_type || SpvOpTypeVoid == value_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpReturnValue value's type '" - << _.getIdName(value->type_id()) << "' is missing or void."; + << "OpReturnValue value's type " + << _.getIdName(value->type_id()) << " is missing or void."; } if (_.addressing_model() == SpvAddressingModelLogical && SpvOpTypePointer == value_type->opcode() && !_.features().variable_pointers && !_.options()->relax_logical_pointer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpReturnValue value's type '" + << "OpReturnValue value's type " << _.getIdName(value->type_id()) - << "' is a pointer, which is invalid in the Logical addressing " + << " is a pointer, which is invalid in the Logical addressing " "model."; } @@ -263,8 +263,8 @@ spv_result_t ValidateReturnValue(ValidationState_t& _, const auto return_type = _.FindDef(function->GetResultTypeId()); if (!return_type || return_type->id() != value_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpReturnValue Value '" << _.getIdName(value_id) - << "'s type does not match OpFunction's return type."; + << "OpReturnValue Value " << _.getIdName(value_id) + << "s type does not match OpFunction's return type."; } return SPV_SUCCESS; @@ -896,14 +896,13 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) { // CFG to ensure we cover all the blocks. std::vector postorder; auto ignore_block = [](const BasicBlock*) {}; - auto ignore_edge = [](const BasicBlock*, const BasicBlock*) {}; auto no_terminal_blocks = [](const BasicBlock*) { return false; }; if (!function.ordered_blocks().empty()) { /// calculate dominators CFA::DepthFirstTraversal( function.first_block(), function.AugmentedCFGSuccessorsFunction(), ignore_block, [&](const BasicBlock* b) { postorder.push_back(b); }, - ignore_edge, no_terminal_blocks); + no_terminal_blocks); auto edges = CFA::CalculateDominators( postorder, function.AugmentedCFGPredecessorsFunction()); for (auto edge : edges) { @@ -953,7 +952,7 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) { CFA::DepthFirstTraversal( function.first_block(), function.AugmentedStructuralCFGSuccessorsFunction(), ignore_block, - [&](const BasicBlock* b) { postorder.push_back(b); }, ignore_edge, + [&](const BasicBlock* b) { postorder.push_back(b); }, no_terminal_blocks); auto edges = CFA::CalculateDominators( postorder, function.AugmentedStructuralCFGPredecessorsFunction()); @@ -967,7 +966,7 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) { function.pseudo_exit_block(), function.AugmentedStructuralCFGPredecessorsFunction(), ignore_block, [&](const BasicBlock* b) { postdom_postorder.push_back(b); }, - ignore_edge, no_terminal_blocks); + no_terminal_blocks); auto postdom_edges = CFA::CalculateDominators( postdom_postorder, function.AugmentedStructuralCFGSuccessorsFunction()); @@ -1067,7 +1066,9 @@ spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) { case SpvOpTerminateInvocation: case SpvOpIgnoreIntersectionKHR: case SpvOpTerminateRayKHR: + case SpvOpEmitMeshTasksEXT: _.current_function().RegisterBlockEnd(std::vector()); + // Ops with dedicated passes check for the Execution Model there if (opcode == SpvOpKill) { _.current_function().RegisterExecutionModelLimitation( SpvExecutionModelFragment, @@ -1081,12 +1082,12 @@ spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) { if (opcode == SpvOpIgnoreIntersectionKHR) { _.current_function().RegisterExecutionModelLimitation( SpvExecutionModelAnyHitKHR, - "OpIgnoreIntersectionKHR requires AnyHit execution model"); + "OpIgnoreIntersectionKHR requires AnyHitKHR execution model"); } if (opcode == SpvOpTerminateRayKHR) { _.current_function().RegisterExecutionModelLimitation( SpvExecutionModelAnyHitKHR, - "OpTerminateRayKHR requires AnyHit execution model"); + "OpTerminateRayKHR requires AnyHitKHR execution model"); } break; diff --git a/3rdparty/spirv-tools/source/val/validate_composites.cpp b/3rdparty/spirv-tools/source/val/validate_composites.cpp index 5d6c5e377..c3d948dc7 100644 --- a/3rdparty/spirv-tools/source/val/validate_composites.cpp +++ b/3rdparty/spirv-tools/source/val/validate_composites.cpp @@ -505,8 +505,8 @@ spv_result_t ValidateVectorShuffle(ValidationState_t& _, if (componentCount != resultVectorDimension) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpVectorShuffle component literals count does not match " - "Result Type '" - << _.getIdName(resultType->id()) << "'s vector component count."; + "Result Type " + << _.getIdName(resultType->id()) << "s vector component count."; } // Vector 1 and Vector 2 must both have vector types, with the same Component diff --git a/3rdparty/spirv-tools/source/val/validate_constants.cpp b/3rdparty/spirv-tools/source/val/validate_constants.cpp index dea95c8a2..fdfaea5f7 100644 --- a/3rdparty/spirv-tools/source/val/validate_constants.cpp +++ b/3rdparty/spirv-tools/source/val/validate_constants.cpp @@ -26,8 +26,8 @@ spv_result_t ValidateConstantBool(ValidationState_t& _, auto type = _.FindDef(inst->type_id()); if (!type || type->opcode() != SpvOpTypeBool) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Op" << spvOpcodeString(inst->opcode()) << " Result Type '" - << _.getIdName(inst->type_id()) << "' is not a boolean type."; + << "Op" << spvOpcodeString(inst->opcode()) << " Result Type " + << _.getIdName(inst->type_id()) << " is not a boolean type."; } return SPV_SUCCESS; @@ -40,8 +40,8 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, const auto result_type = _.FindDef(inst->type_id()); if (!result_type || !spvOpcodeIsComposite(result_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Result Type '" - << _.getIdName(inst->type_id()) << "' is not a composite type."; + << opcode_name << " Result Type " + << _.getIdName(inst->type_id()) << " is not a composite type."; } const auto constituent_count = inst->words().size() - 3; @@ -53,9 +53,8 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, return _.diag(SPV_ERROR_INVALID_ID, inst) << opcode_name << " Constituent count does not match " - "Result Type '" - << _.getIdName(result_type->id()) - << "'s vector component count."; + "Result Type " + << _.getIdName(result_type->id()) << "s vector component count."; } const auto component_type = _.FindDef(result_type->GetOperandAs(1)); @@ -71,18 +70,18 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, if (!constituent || !spvOpcodeIsConstantOrUndef(constituent->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' is not a constant or undef."; + << " is not a constant or undef."; } const auto constituent_result_type = _.FindDef(constituent->type_id()); if (!constituent_result_type || component_type->opcode() != constituent_result_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "'s type does not match Result Type '" - << _.getIdName(result_type->id()) << "'s vector element type."; + << "s type does not match Result Type " + << _.getIdName(result_type->id()) << "s vector element type."; } } } break; @@ -93,8 +92,8 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, return _.diag(SPV_ERROR_INVALID_ID, inst) << opcode_name << " Constituent count does not match " - "Result Type '" - << _.getIdName(result_type->id()) << "'s matrix column count."; + "Result Type " + << _.getIdName(result_type->id()) << "s matrix column count."; } const auto column_type = _.FindDef(result_type->words()[2]); @@ -120,9 +119,9 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, // The message says "... or undef" because the spec does not say // undef is a constant. return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' is not a constant or undef."; + << " is not a constant or undef."; } const auto vector = _.FindDef(constituent->type_id()); if (!vector) { @@ -131,28 +130,28 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, } if (column_type->opcode() != vector->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' type does not match Result Type '" - << _.getIdName(result_type->id()) << "'s matrix column type."; + << " type does not match Result Type " + << _.getIdName(result_type->id()) << "s matrix column type."; } const auto vector_component_type = _.FindDef(vector->GetOperandAs(1)); if (component_type->id() != vector_component_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' component type does not match Result Type '" + << " component type does not match Result Type " << _.getIdName(result_type->id()) - << "'s matrix column component type."; + << "s matrix column component type."; } if (component_count != vector->words()[3]) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' vector component count does not match Result Type '" + << " vector component count does not match Result Type " << _.getIdName(result_type->id()) - << "'s vector component count."; + << "s vector component count."; } } } break; @@ -175,8 +174,8 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, return _.diag(SPV_ERROR_INVALID_ID, inst) << opcode_name << " Constituent count does not match " - "Result Type '" - << _.getIdName(result_type->id()) << "'s array length."; + "Result Type " + << _.getIdName(result_type->id()) << "s array length."; } for (size_t constituent_index = 2; constituent_index < inst->operands().size(); constituent_index++) { @@ -186,9 +185,9 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, if (!constituent || !spvOpcodeIsConstantOrUndef(constituent->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' is not a constant or undef."; + << " is not a constant or undef."; } const auto constituent_type = _.FindDef(constituent->type_id()); if (!constituent_type) { @@ -197,10 +196,10 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, } if (element_type->id() != constituent_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "'s type does not match Result Type '" - << _.getIdName(result_type->id()) << "'s array element type."; + << "s type does not match Result Type " + << _.getIdName(result_type->id()) << "s array element type."; } } } break; @@ -208,10 +207,10 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, const auto member_count = result_type->words().size() - 2; if (member_count != constituent_count) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(inst->type_id()) - << "' count does not match Result Type '" - << _.getIdName(result_type->id()) << "'s struct member count."; + << " count does not match Result Type " + << _.getIdName(result_type->id()) << "s struct member count."; } for (uint32_t constituent_index = 2, member_index = 1; constituent_index < inst->operands().size(); @@ -222,9 +221,9 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, if (!constituent || !spvOpcodeIsConstantOrUndef(constituent->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' is not a constant or undef."; + << " is not a constant or undef."; } const auto constituent_type = _.FindDef(constituent->type_id()); if (!constituent_type) { @@ -237,26 +236,25 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, const auto member_type = _.FindDef(member_type_id); if (!member_type || member_type->id() != constituent_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' type does not match the Result Type '" - << _.getIdName(result_type->id()) << "'s member type."; + << " type does not match the Result Type " + << _.getIdName(result_type->id()) << "s member type."; } } } break; case SpvOpTypeCooperativeMatrixNV: { if (1 != constituent_count) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" - << _.getIdName(inst->type_id()) << "' count must be one."; + << opcode_name << " Constituent " + << _.getIdName(inst->type_id()) << " count must be one."; } const auto constituent_id = inst->GetOperandAs(2); const auto constituent = _.FindDef(constituent_id); if (!constituent || !spvOpcodeIsConstantOrUndef(constituent->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" - << _.getIdName(constituent_id) - << "' is not a constant or undef."; + << opcode_name << " Constituent " + << _.getIdName(constituent_id) << " is not a constant or undef."; } const auto constituent_type = _.FindDef(constituent->type_id()); if (!constituent_type) { @@ -268,10 +266,10 @@ spv_result_t ValidateConstantComposite(ValidationState_t& _, const auto component_type = _.FindDef(component_type_id); if (!component_type || component_type->id() != constituent_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opcode_name << " Constituent '" + << opcode_name << " Constituent " << _.getIdName(constituent_id) - << "' type does not match the Result Type '" - << _.getIdName(result_type->id()) << "'s component type."; + << " type does not match the Result Type " + << _.getIdName(result_type->id()) << "s component type."; } } break; default: @@ -285,8 +283,8 @@ spv_result_t ValidateConstantSampler(ValidationState_t& _, const auto result_type = _.FindDef(inst->type_id()); if (!result_type || result_type->opcode() != SpvOpTypeSampler) { return _.diag(SPV_ERROR_INVALID_ID, result_type) - << "OpConstantSampler Result Type '" - << _.getIdName(inst->type_id()) << "' is not a sampler type."; + << "OpConstantSampler Result Type " + << _.getIdName(inst->type_id()) << " is not a sampler type."; } return SPV_SUCCESS; @@ -339,8 +337,8 @@ spv_result_t ValidateConstantNull(ValidationState_t& _, const auto result_type = _.FindDef(inst->type_id()); if (!result_type || !IsTypeNullable(result_type->words(), _)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpConstantNull Result Type '" - << _.getIdName(inst->type_id()) << "' cannot have a null value."; + << "OpConstantNull Result Type " << _.getIdName(inst->type_id()) + << " cannot have a null value."; } return SPV_SUCCESS; diff --git a/3rdparty/spirv-tools/source/val/validate_debug.cpp b/3rdparty/spirv-tools/source/val/validate_debug.cpp index 0a25d8ab7..7ab597a11 100644 --- a/3rdparty/spirv-tools/source/val/validate_debug.cpp +++ b/3rdparty/spirv-tools/source/val/validate_debug.cpp @@ -28,16 +28,16 @@ spv_result_t ValidateMemberName(ValidationState_t& _, const Instruction* inst) { const auto type = _.FindDef(type_id); if (!type || SpvOpTypeStruct != type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpMemberName Type '" << _.getIdName(type_id) - << "' is not a struct type."; + << "OpMemberName Type " << _.getIdName(type_id) + << " is not a struct type."; } const auto member_id = inst->GetOperandAs(1); const auto member_count = (uint32_t)(type->words().size() - 2); if (member_count <= member_id) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpMemberName Member '" << _.getIdName(member_id) - << "' index is larger than Type '" << _.getIdName(type->id()) - << "'s member count."; + << "OpMemberName Member " << _.getIdName(member_id) + << " index is larger than Type " << _.getIdName(type->id()) + << "s member count."; } return SPV_SUCCESS; } @@ -47,8 +47,8 @@ spv_result_t ValidateLine(ValidationState_t& _, const Instruction* inst) { const auto file = _.FindDef(file_id); if (!file || SpvOpString != file->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpLine Target '" << _.getIdName(file_id) - << "' is not an OpString."; + << "OpLine Target " << _.getIdName(file_id) + << " is not an OpString."; } return SPV_SUCCESS; } diff --git a/3rdparty/spirv-tools/source/val/validate_decorations.cpp b/3rdparty/spirv-tools/source/val/validate_decorations.cpp index 4e4f10860..75058501e 100644 --- a/3rdparty/spirv-tools/source/val/validate_decorations.cpp +++ b/3rdparty/spirv-tools/source/val/validate_decorations.cpp @@ -179,8 +179,9 @@ uint32_t align(uint32_t x, uint32_t alignment) { } // Returns base alignment of struct member. If |roundUp| is true, also -// ensure that structs and arrays are aligned at least to a multiple of 16 -// bytes. +// ensure that structs, arrays, and matrices are aligned at least to a +// multiple of 16 bytes. (That is, when roundUp is true, this function +// returns the *extended* alignment as it's called by the Vulkan spec.) uint32_t getBaseAlignment(uint32_t member_id, bool roundUp, const LayoutConstraints& inherited, MemberConstraints& constraints, @@ -1295,32 +1296,6 @@ bool AtMostOncePerMember(SpvDecoration decoration) { } } -// Returns the string name for |decoration|. -const char* GetDecorationName(SpvDecoration decoration) { - switch (decoration) { - case SpvDecorationAliased: - return "Aliased"; - case SpvDecorationRestrict: - return "Restrict"; - case SpvDecorationArrayStride: - return "ArrayStride"; - case SpvDecorationOffset: - return "Offset"; - case SpvDecorationMatrixStride: - return "MatrixStride"; - case SpvDecorationRowMajor: - return "RowMajor"; - case SpvDecorationColMajor: - return "ColMajor"; - case SpvDecorationBlock: - return "Block"; - case SpvDecorationBufferBlock: - return "BufferBlock"; - default: - return ""; - } -} - spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) { using PerIDKey = std::tuple; using PerMemberKey = std::tuple; @@ -1353,7 +1328,7 @@ spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) { if (already_used && AtMostOncePerId(dec_type)) { return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id)) << "ID '" << id << "' decorated with " - << GetDecorationName(dec_type) + << vstate.SpvDecorationString(dec_type) << " multiple times is not allowed."; } // Verify certain mutually exclusive decorations are not both applied on @@ -1373,8 +1348,9 @@ spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) { if (seen_per_id.find(excl_k) != seen_per_id.end()) { return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id)) << "ID '" << id << "' decorated with both " - << GetDecorationName(dec_type) << " and " - << GetDecorationName(excl_dec_type) << " is not allowed."; + << vstate.SpvDecorationString(dec_type) << " and " + << vstate.SpvDecorationString(excl_dec_type) + << " is not allowed."; } } } else if (SpvOpMemberDecorate == inst.opcode()) { @@ -1386,7 +1362,7 @@ spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) { if (already_used && AtMostOncePerMember(dec_type)) { return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id)) << "ID '" << id << "', member '" << member_id - << "' decorated with " << GetDecorationName(dec_type) + << "' decorated with " << vstate.SpvDecorationString(dec_type) << " multiple times is not allowed."; } // Verify certain mutually exclusive decorations are not both applied on @@ -1406,8 +1382,9 @@ spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) { if (seen_per_member.find(excl_k) != seen_per_member.end()) { return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id)) << "ID '" << id << "', member '" << member_id - << "' decorated with both " << GetDecorationName(dec_type) - << " and " << GetDecorationName(excl_dec_type) + << "' decorated with both " + << vstate.SpvDecorationString(dec_type) << " and " + << vstate.SpvDecorationString(excl_dec_type) << " is not allowed."; } } diff --git a/3rdparty/spirv-tools/source/val/validate_execution_limitations.cpp b/3rdparty/spirv-tools/source/val/validate_execution_limitations.cpp index aac1c4987..e1f4d7b04 100644 --- a/3rdparty/spirv-tools/source/val/validate_execution_limitations.cpp +++ b/3rdparty/spirv-tools/source/val/validate_execution_limitations.cpp @@ -44,8 +44,8 @@ spv_result_t ValidateExecutionLimitations(ValidationState_t& _, std::string reason; if (!func->IsCompatibleWithExecutionModel(model, &reason)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpEntryPoint Entry Point '" << _.getIdName(entry_id) - << "'s callgraph contains function " + << "OpEntryPoint Entry Point " << _.getIdName(entry_id) + << "s callgraph contains function " << _.getIdName(inst->id()) << ", which cannot be used with the current execution " "model:\n" @@ -57,9 +57,8 @@ spv_result_t ValidateExecutionLimitations(ValidationState_t& _, std::string reason; if (!func->CheckLimitations(_, _.function(entry_id), &reason)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpEntryPoint Entry Point '" << _.getIdName(entry_id) - << "'s callgraph contains function " - << _.getIdName(inst->id()) + << "OpEntryPoint Entry Point " << _.getIdName(entry_id) + << "s callgraph contains function " << _.getIdName(inst->id()) << ", which cannot be used with the current execution " "modes:\n" << reason; diff --git a/3rdparty/spirv-tools/source/val/validate_extensions.cpp b/3rdparty/spirv-tools/source/val/validate_extensions.cpp index fcf04e207..1e69cb37f 100644 --- a/3rdparty/spirv-tools/source/val/validate_extensions.cpp +++ b/3rdparty/spirv-tools/source/val/validate_extensions.cpp @@ -756,10 +756,10 @@ spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) { if (_.version() < SPV_SPIRV_VERSION_WORD(1, 4)) { std::string extension = GetExtensionString(&(inst->c_inst())); if (extension == - ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout)) { + ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout) || + extension == ExtensionToString(kSPV_EXT_mesh_shader)) { return _.diag(SPV_ERROR_WRONG_VERSION, inst) - << "SPV_KHR_workgroup_memory_explicit_layout extension " - "requires SPIR-V version 1.4 or later."; + << extension << " extension requires SPIR-V version 1.4 or later."; } } diff --git a/3rdparty/spirv-tools/source/val/validate_function.cpp b/3rdparty/spirv-tools/source/val/validate_function.cpp index 2a5fed8e2..0ccf5a9ea 100644 --- a/3rdparty/spirv-tools/source/val/validate_function.cpp +++ b/3rdparty/spirv-tools/source/val/validate_function.cpp @@ -58,16 +58,16 @@ spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) { const auto function_type = _.FindDef(function_type_id); if (!function_type || SpvOpTypeFunction != function_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpFunction Function Type '" << _.getIdName(function_type_id) - << "' is not a function type."; + << "OpFunction Function Type " << _.getIdName(function_type_id) + << " is not a function type."; } const auto return_id = function_type->GetOperandAs(1); if (return_id != inst->type_id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpFunction Result Type '" << _.getIdName(inst->type_id()) - << "' does not match the Function Type's return type '" - << _.getIdName(return_id) << "'."; + << "OpFunction Result Type " << _.getIdName(inst->type_id()) + << " does not match the Function Type's return type " + << _.getIdName(return_id) << "."; } const std::vector acceptable = { @@ -141,9 +141,9 @@ spv_result_t ValidateFunctionParameter(ValidationState_t& _, _.FindDef(function_type->GetOperandAs(param_index + 2)); if (!param_type || inst->type_id() != param_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpFunctionParameter Result Type '" + << "OpFunctionParameter Result Type " << _.getIdName(inst->type_id()) - << "' does not match the OpTypeFunction parameter " + << " does not match the OpTypeFunction parameter " "type of the same index."; } @@ -228,17 +228,16 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _, const auto function = _.FindDef(function_id); if (!function || SpvOpFunction != function->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpFunctionCall Function '" << _.getIdName(function_id) - << "' is not a function."; + << "OpFunctionCall Function " << _.getIdName(function_id) + << " is not a function."; } auto return_type = _.FindDef(function->type_id()); if (!return_type || return_type->id() != inst->type_id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpFunctionCall Result Type '" - << _.getIdName(inst->type_id()) - << "'s type does not match Function '" - << _.getIdName(return_type->id()) << "'s return type."; + << "OpFunctionCall Result Type " << _.getIdName(inst->type_id()) + << "s type does not match Function " + << _.getIdName(return_type->id()) << "s return type."; } const auto function_type_id = function->GetOperandAs(3); @@ -280,9 +279,9 @@ spv_result_t ValidateFunctionCall(ValidationState_t& _, if (!_.options()->before_hlsl_legalization || !DoPointeesLogicallyMatch(argument_type, parameter_type, _)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpFunctionCall Argument '" << _.getIdName(argument_id) - << "'s type does not match Function '" - << _.getIdName(parameter_type_id) << "'s parameter type."; + << "OpFunctionCall Argument " << _.getIdName(argument_id) + << "s type does not match Function " + << _.getIdName(parameter_type_id) << "s parameter type."; } } diff --git a/3rdparty/spirv-tools/source/val/validate_image.cpp b/3rdparty/spirv-tools/source/val/validate_image.cpp index 2d5e2c7c5..9c7c8c1c1 100644 --- a/3rdparty/spirv-tools/source/val/validate_image.cpp +++ b/3rdparty/spirv-tools/source/val/validate_image.cpp @@ -1020,11 +1020,11 @@ spv_result_t ValidateSampledImage(ValidationState_t& _, << "All OpSampledImage instructions must be in the same block " "in " "which their Result are consumed. OpSampledImage Result " - "Type '" + "Type " << _.getIdName(inst->id()) - << "' has a consumer in a different basic " - "block. The consumer instruction is '" - << _.getIdName(consumer_instr->id()) << "'."; + << " has a consumer in a different basic " + "block. The consumer instruction is " + << _.getIdName(consumer_instr->id()) << "."; } if (consumer_opcode == SpvOpPhi || consumer_opcode == SpvOpSelect) { @@ -1033,9 +1033,9 @@ spv_result_t ValidateSampledImage(ValidationState_t& _, "as " "operands of Op" << spvOpcodeString(static_cast(consumer_opcode)) << "." - << " Found result '" << _.getIdName(inst->id()) - << "' as an operand of '" - << _.getIdName(consumer_instr->id()) << "'."; + << " Found result " << _.getIdName(inst->id()) + << " as an operand of " << _.getIdName(consumer_instr->id()) + << "."; } if (!IsAllowedSampledImageOperand(consumer_opcode, _)) { @@ -1045,9 +1045,9 @@ spv_result_t ValidateSampledImage(ValidationState_t& _, << spvOpcodeString(static_cast(consumer_opcode)) << ", since it is not specified as taking an " << "OpTypeSampledImage." - << " Found result '" << _.getIdName(inst->id()) - << "' as an operand of '" - << _.getIdName(consumer_instr->id()) << "'."; + << " Found result " << _.getIdName(inst->id()) + << " as an operand of " << _.getIdName(consumer_instr->id()) + << "."; } } } @@ -1689,8 +1689,7 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) { << " components, but given only " << actual_coord_size; } - // TODO(atgoo@github.com) The spec doesn't explicitly say what the type - // of texel should be. + // because it needs to match with 'Sampled Type' the Texel can't be a boolean const uint32_t texel_type = _.GetOperandTypeId(inst, 2); if (!_.IsIntScalarOrVectorType(texel_type) && !_.IsFloatScalarOrVectorType(texel_type)) { @@ -1698,14 +1697,6 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) { << "Expected Texel to be int or float vector or scalar"; } -#if 0 - // TODO: See above. - if (_.GetDimension(texel_type) != 4) { - return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "Expected Texel to have 4 components"; - } -#endif - if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) { const uint32_t texel_component_type = _.GetComponentType(texel_type); if (texel_component_type != info.sampled_type) { diff --git a/3rdparty/spirv-tools/source/val/validate_memory.cpp b/3rdparty/spirv-tools/source/val/validate_memory.cpp index 425a8d3d2..074bdb88a 100644 --- a/3rdparty/spirv-tools/source/val/validate_memory.cpp +++ b/3rdparty/spirv-tools/source/val/validate_memory.cpp @@ -402,8 +402,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { auto result_type = _.FindDef(inst->type_id()); if (!result_type || result_type->opcode() != SpvOpTypePointer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpVariable Result Type '" << _.getIdName(inst->type_id()) - << "' is not a pointer type."; + << "OpVariable Result Type " << _.getIdName(inst->type_id()) + << " is not a pointer type."; } const auto type_index = 2; @@ -423,8 +423,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { initializer && spvOpcodeIsConstant(initializer->opcode()); if (!initializer || !(is_constant || is_module_scope_var)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpVariable Initializer '" << _.getIdName(initializer_id) - << "' is not a constant or module-scope variable."; + << "OpVariable Initializer " << _.getIdName(initializer_id) + << " is not a constant or module-scope variable."; } if (initializer->type_id() != value_id) { return _.diag(SPV_ERROR_INVALID_ID, inst) @@ -438,11 +438,12 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { storage_class != SpvStorageClassCrossWorkgroup && storage_class != SpvStorageClassPrivate && storage_class != SpvStorageClassFunction && - storage_class != SpvStorageClassRayPayloadNV && - storage_class != SpvStorageClassIncomingRayPayloadNV && - storage_class != SpvStorageClassHitAttributeNV && - storage_class != SpvStorageClassCallableDataNV && - storage_class != SpvStorageClassIncomingCallableDataNV) { + storage_class != SpvStorageClassRayPayloadKHR && + storage_class != SpvStorageClassIncomingRayPayloadKHR && + storage_class != SpvStorageClassHitAttributeKHR && + storage_class != SpvStorageClassCallableDataKHR && + storage_class != SpvStorageClassIncomingCallableDataKHR && + storage_class != SpvStorageClassTaskPayloadWorkgroupEXT) { bool storage_input_or_output = storage_class == SpvStorageClassInput || storage_class == SpvStorageClassOutput; bool builtin = false; @@ -454,12 +455,24 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { } } } - if (!(storage_input_or_output && builtin) && + if (!builtin && ContainsInvalidBool(_, value_type, storage_input_or_output)) { - return _.diag(SPV_ERROR_INVALID_ID, inst) - << "If OpTypeBool is stored in conjunction with OpVariable, it " - << "can only be used with non-externally visible shader Storage " - << "Classes: Workgroup, CrossWorkgroup, Private, and Function"; + if (storage_input_or_output) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << _.VkErrorID(7290) + << "If OpTypeBool is stored in conjunction with OpVariable " + "using Input or Output Storage Classes it requires a BuiltIn " + "decoration"; + + } else { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "If OpTypeBool is stored in conjunction with OpVariable, it " + "can only be used with non-externally visible shader Storage " + "Classes: Workgroup, CrossWorkgroup, Private, Function, " + "Input, Output, RayPayloadKHR, IncomingRayPayloadKHR, " + "HitAttributeKHR, CallableDataKHR, or " + "IncomingCallableDataKHR"; + } } } @@ -524,8 +537,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { if (storage_class == SpvStorageClassPushConstant) { if (pointee->opcode() != SpvOpTypeStruct) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(6808) << "PushConstant OpVariable '" - << _.getIdName(inst->id()) << "' has illegal type.\n" + << _.VkErrorID(6808) << "PushConstant OpVariable " + << _.getIdName(inst->id()) << " has illegal type.\n" << "From Vulkan spec, Push Constant Interface section:\n" << "Such variables must be typed as OpTypeStruct"; } @@ -539,8 +552,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { {SpvOpTypeImage, SpvOpTypeSampler, SpvOpTypeSampledImage, SpvOpTypeAccelerationStructureKHR})) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4655) << "UniformConstant OpVariable '" - << _.getIdName(inst->id()) << "' has illegal type.\n" + << _.VkErrorID(4655) << "UniformConstant OpVariable " + << _.getIdName(inst->id()) << " has illegal type.\n" << "Variables identified with the UniformConstant storage class " << "are used only as handles to refer to opaque resources. Such " << "variables must be typed as OpTypeImage, OpTypeSampler, " @@ -552,8 +565,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { if (storage_class == SpvStorageClassUniform) { if (!IsAllowedTypeOrArrayOfSame(_, pointee, {SpvOpTypeStruct})) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(6807) << "Uniform OpVariable '" - << _.getIdName(inst->id()) << "' has illegal type.\n" + << _.VkErrorID(6807) << "Uniform OpVariable " + << _.getIdName(inst->id()) << " has illegal type.\n" << "From Vulkan spec:\n" << "Variables identified with the Uniform storage class are " << "used to access transparent buffer backed resources. Such " @@ -565,8 +578,8 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { if (storage_class == SpvStorageClassStorageBuffer) { if (!IsAllowedTypeOrArrayOfSame(_, pointee, {SpvOpTypeStruct})) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(6807) << "StorageBuffer OpVariable '" - << _.getIdName(inst->id()) << "' has illegal type.\n" + << _.VkErrorID(6807) << "StorageBuffer OpVariable " + << _.getIdName(inst->id()) << " has illegal type.\n" << "From Vulkan spec:\n" << "Variables identified with the StorageBuffer storage class " "are used to access transparent buffer backed resources. " @@ -604,9 +617,9 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { auto init = _.FindDef(init_id); if (init->opcode() != SpvOpConstantNull) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4734) << "OpVariable, '" + << _.VkErrorID(4734) << "OpVariable, " << _.getIdName(inst->id()) - << "', initializers are limited to OpConstantNull in " + << ", initializers are limited to OpConstantNull in " "Workgroup " "storage class"; } @@ -614,9 +627,9 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { storage_class != SpvStorageClassPrivate && storage_class != SpvStorageClassFunction) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4651) << "OpVariable, '" + << _.VkErrorID(4651) << "OpVariable, " << _.getIdName(inst->id()) - << "', has a disallowed initializer & storage class " + << ", has a disallowed initializer & storage class " << "combination.\n" << "From " << spvLogStringForEnv(_.context()->target_env) << " spec:\n" @@ -627,6 +640,19 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { } } + if (inst->operands().size() > 3) { + if (storage_class == SpvStorageClassTaskPayloadWorkgroupEXT) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpVariable, " << _.getIdName(inst->id()) + << ", initializer are not allowed for TaskPayloadWorkgroupEXT"; + } + if (storage_class == SpvStorageClassInput) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "OpVariable, " << _.getIdName(inst->id()) + << ", initializer are not allowed for Input"; + } + } + if (storage_class == SpvStorageClassPhysicalStorageBuffer) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "PhysicalStorageBuffer must not be used with OpVariable."; @@ -667,9 +693,9 @@ spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { if (value_type && value_type->opcode() == SpvOpTypeRuntimeArray) { if (!_.HasCapability(SpvCapabilityRuntimeDescriptorArrayEXT)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4680) << "OpVariable, '" + << _.VkErrorID(4680) << "OpVariable, " << _.getIdName(inst->id()) - << "', is attempting to create memory for an illegal type, " + << ", is attempting to create memory for an illegal type, " << "OpTypeRuntimeArray.\nFor Vulkan OpTypeRuntimeArray can only " << "appear as the final member of an OpTypeStruct, thus cannot " << "be instantiated via OpVariable"; @@ -864,8 +890,8 @@ spv_result_t ValidateLoad(ValidationState_t& _, const Instruction* inst) { const auto result_type = _.FindDef(inst->type_id()); if (!result_type) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpLoad Result Type '" << _.getIdName(inst->type_id()) - << "' is not defined."; + << "OpLoad Result Type " << _.getIdName(inst->type_id()) + << " is not defined."; } const auto pointer_index = 2; @@ -878,23 +904,26 @@ spv_result_t ValidateLoad(ValidationState_t& _, const Instruction* inst) { (_.features().variable_pointers && !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpLoad Pointer '" << _.getIdName(pointer_id) - << "' is not a logical pointer."; + << "OpLoad Pointer " << _.getIdName(pointer_id) + << " is not a logical pointer."; } const auto pointer_type = _.FindDef(pointer->type_id()); if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpLoad type for pointer '" << _.getIdName(pointer_id) - << "' is not a pointer type."; + << "OpLoad type for pointer " << _.getIdName(pointer_id) + << " is not a pointer type."; } - const auto pointee_type = _.FindDef(pointer_type->GetOperandAs(2)); - if (!pointee_type || result_type->id() != pointee_type->id()) { + uint32_t pointee_data_type; + uint32_t storage_class; + if (!_.GetPointerTypeInfo(pointer_type->id(), &pointee_data_type, + &storage_class) || + result_type->id() != pointee_data_type) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpLoad Result Type '" << _.getIdName(inst->type_id()) - << "' does not match Pointer '" << _.getIdName(pointer->id()) - << "'s type."; + << "OpLoad Result Type " << _.getIdName(inst->type_id()) + << " does not match Pointer " << _.getIdName(pointer->id()) + << "s type."; } if (!_.options()->before_hlsl_legalization && @@ -931,21 +960,21 @@ spv_result_t ValidateStore(ValidationState_t& _, const Instruction* inst) { (_.features().variable_pointers && !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Pointer '" << _.getIdName(pointer_id) - << "' is not a logical pointer."; + << "OpStore Pointer " << _.getIdName(pointer_id) + << " is not a logical pointer."; } const auto pointer_type = _.FindDef(pointer->type_id()); if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore type for pointer '" << _.getIdName(pointer_id) - << "' is not a pointer type."; + << "OpStore type for pointer " << _.getIdName(pointer_id) + << " is not a pointer type."; } const auto type_id = pointer_type->GetOperandAs(2); const auto type = _.FindDef(type_id); if (!type || SpvOpTypeVoid == type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Pointer '" << _.getIdName(pointer_id) - << "'s type is void."; + << "OpStore Pointer " << _.getIdName(pointer_id) + << "s type is void."; } // validate storage class @@ -954,16 +983,36 @@ spv_result_t ValidateStore(ValidationState_t& _, const Instruction* inst) { uint32_t storage_class; if (!_.GetPointerTypeInfo(pointer_type->id(), &data_type, &storage_class)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Pointer '" << _.getIdName(pointer_id) - << "' is not pointer type"; + << "OpStore Pointer " << _.getIdName(pointer_id) + << " is not pointer type"; } if (storage_class == SpvStorageClassUniformConstant || storage_class == SpvStorageClassInput || storage_class == SpvStorageClassPushConstant) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Pointer '" << _.getIdName(pointer_id) - << "' storage class is read-only"; + << "OpStore Pointer " << _.getIdName(pointer_id) + << " storage class is read-only"; + } else if (storage_class == SpvStorageClassShaderRecordBufferKHR) { + return _.diag(SPV_ERROR_INVALID_ID, inst) + << "ShaderRecordBufferKHR Storage Class variables are read only"; + } else if (storage_class == SpvStorageClassHitAttributeKHR) { + std::string errorVUID = _.VkErrorID(4703); + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model == SpvExecutionModelAnyHitKHR || + model == SpvExecutionModelClosestHitKHR) { + if (message) { + *message = + errorVUID + + "HitAttributeKHR Storage Class variables are read only " + "with AnyHitKHR and ClosestHitKHR"; + } + return false; + } + return true; + }); } if (spvIsVulkanEnv(_.context()->target_env) && @@ -992,31 +1041,31 @@ spv_result_t ValidateStore(ValidationState_t& _, const Instruction* inst) { const auto object = _.FindDef(object_id); if (!object || !object->type_id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Object '" << _.getIdName(object_id) - << "' is not an object."; + << "OpStore Object " << _.getIdName(object_id) + << " is not an object."; } const auto object_type = _.FindDef(object->type_id()); if (!object_type || SpvOpTypeVoid == object_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Object '" << _.getIdName(object_id) - << "'s type is void."; + << "OpStore Object " << _.getIdName(object_id) + << "s type is void."; } if (type->id() != object_type->id()) { if (!_.options()->relax_struct_store || type->opcode() != SpvOpTypeStruct || object_type->opcode() != SpvOpTypeStruct) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Pointer '" << _.getIdName(pointer_id) - << "'s type does not match Object '" - << _.getIdName(object->id()) << "'s type."; + << "OpStore Pointer " << _.getIdName(pointer_id) + << "s type does not match Object " + << _.getIdName(object->id()) << "s type."; } // TODO: Check for layout compatible matricies and arrays as well. if (!AreLayoutCompatibleStructs(_, type, object_type)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpStore Pointer '" << _.getIdName(pointer_id) - << "'s layout does not match Object '" - << _.getIdName(object->id()) << "'s layout."; + << "OpStore Pointer " << _.getIdName(pointer_id) + << "s layout does not match Object " + << _.getIdName(object->id()) << "s layout."; } } @@ -1088,8 +1137,8 @@ spv_result_t ValidateCopyMemory(ValidationState_t& _, const Instruction* inst) { const auto target = _.FindDef(target_id); if (!target) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Target operand '" << _.getIdName(target_id) - << "' is not defined."; + << "Target operand " << _.getIdName(target_id) + << " is not defined."; } const auto source_index = 1; @@ -1097,24 +1146,24 @@ spv_result_t ValidateCopyMemory(ValidationState_t& _, const Instruction* inst) { const auto source = _.FindDef(source_id); if (!source) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Source operand '" << _.getIdName(source_id) - << "' is not defined."; + << "Source operand " << _.getIdName(source_id) + << " is not defined."; } const auto target_pointer_type = _.FindDef(target->type_id()); if (!target_pointer_type || target_pointer_type->opcode() != SpvOpTypePointer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Target operand '" << _.getIdName(target_id) - << "' is not a pointer."; + << "Target operand " << _.getIdName(target_id) + << " is not a pointer."; } const auto source_pointer_type = _.FindDef(source->type_id()); if (!source_pointer_type || source_pointer_type->opcode() != SpvOpTypePointer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Source operand '" << _.getIdName(source_id) - << "' is not a pointer."; + << "Source operand " << _.getIdName(source_id) + << " is not a pointer."; } if (inst->opcode() == SpvOpCopyMemory) { @@ -1122,60 +1171,60 @@ spv_result_t ValidateCopyMemory(ValidationState_t& _, const Instruction* inst) { _.FindDef(target_pointer_type->GetOperandAs(2)); if (!target_type || target_type->opcode() == SpvOpTypeVoid) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Target operand '" << _.getIdName(target_id) - << "' cannot be a void pointer."; + << "Target operand " << _.getIdName(target_id) + << " cannot be a void pointer."; } const auto source_type = _.FindDef(source_pointer_type->GetOperandAs(2)); if (!source_type || source_type->opcode() == SpvOpTypeVoid) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Source operand '" << _.getIdName(source_id) - << "' cannot be a void pointer."; + << "Source operand " << _.getIdName(source_id) + << " cannot be a void pointer."; } if (target_type->id() != source_type->id()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Target '" << _.getIdName(source_id) - << "'s type does not match Source '" - << _.getIdName(source_type->id()) << "'s type."; + << "Target " << _.getIdName(source_id) + << "s type does not match Source " + << _.getIdName(source_type->id()) << "s type."; } } else { const auto size_id = inst->GetOperandAs(2); const auto size = _.FindDef(size_id); if (!size) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Size operand '" << _.getIdName(size_id) - << "' is not defined."; + << "Size operand " << _.getIdName(size_id) + << " is not defined."; } const auto size_type = _.FindDef(size->type_id()); if (!_.IsIntScalarType(size_type->id())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Size operand '" << _.getIdName(size_id) - << "' must be a scalar integer type."; + << "Size operand " << _.getIdName(size_id) + << " must be a scalar integer type."; } bool is_zero = true; switch (size->opcode()) { case SpvOpConstantNull: return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Size operand '" << _.getIdName(size_id) - << "' cannot be a constant zero."; + << "Size operand " << _.getIdName(size_id) + << " cannot be a constant zero."; case SpvOpConstant: if (size_type->word(3) == 1 && size->word(size->words().size() - 1) & 0x80000000) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Size operand '" << _.getIdName(size_id) - << "' cannot have the sign bit set to 1."; + << "Size operand " << _.getIdName(size_id) + << " cannot have the sign bit set to 1."; } for (size_t i = 3; is_zero && i < size->words().size(); ++i) { is_zero &= (size->word(i) == 0); } if (is_zero) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Size operand '" << _.getIdName(size_id) - << "' cannot be a constant zero."; + << "Size operand " << _.getIdName(size_id) + << " cannot be a constant zero."; } break; default: @@ -1208,8 +1257,8 @@ spv_result_t ValidateAccessChain(ValidationState_t& _, auto result_type = _.FindDef(inst->type_id()); if (SpvOpTypePointer != result_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "The Result Type of " << instr_name << " '" - << _.getIdName(inst->id()) << "' must be OpTypePointer. Found Op" + << "The Result Type of " << instr_name << " " + << _.getIdName(inst->id()) << " must be OpTypePointer. Found Op" << spvOpcodeString(static_cast(result_type->opcode())) << "."; } @@ -1225,7 +1274,7 @@ spv_result_t ValidateAccessChain(ValidationState_t& _, const auto base_type = _.FindDef(base->type_id()); if (!base_type || SpvOpTypePointer != base_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "The Base '" << _.getIdName(base_id) << "' in " << instr_name + << "The Base " << _.getIdName(base_id) << " in " << instr_name << " instruction must be a pointer."; } @@ -1317,8 +1366,8 @@ spv_result_t ValidateAccessChain(ValidationState_t& _, return _.diag(SPV_ERROR_INVALID_ID, cur_word_instr) << "Index is out of bounds: " << instr_name << " can not find index " << cur_index - << " into the structure '" - << _.getIdName(type_pointee->id()) << "'. This structure has " + << " into the structure " + << _.getIdName(type_pointee->id()) << ". This structure has " << num_struct_members << " members. Largest valid index is " << num_struct_members - 1 << "."; } @@ -1375,9 +1424,9 @@ spv_result_t ValidateArrayLength(ValidationState_t& state, result_type->GetOperandAs(1) != 32 || result_type->GetOperandAs(2) != 0) { return state.diag(SPV_ERROR_INVALID_ID, inst) - << "The Result Type of " << instr_name << " '" + << "The Result Type of " << instr_name << " " << state.getIdName(inst->id()) - << "' must be OpTypeInt with width 32 and signedness 0."; + << " must be OpTypeInt with width 32 and signedness 0."; } // The structure that is passed in must be an pointer to a structure, whose @@ -1386,17 +1435,17 @@ spv_result_t ValidateArrayLength(ValidationState_t& state, auto pointer_type = state.FindDef(pointer->type_id()); if (pointer_type->opcode() != SpvOpTypePointer) { return state.diag(SPV_ERROR_INVALID_ID, inst) - << "The Struture's type in " << instr_name << " '" + << "The Structure's type in " << instr_name << " " << state.getIdName(inst->id()) - << "' must be a pointer to an OpTypeStruct."; + << " must be a pointer to an OpTypeStruct."; } auto structure_type = state.FindDef(pointer_type->GetOperandAs(2)); if (structure_type->opcode() != SpvOpTypeStruct) { return state.diag(SPV_ERROR_INVALID_ID, inst) - << "The Struture's type in " << instr_name << " '" + << "The Structure's type in " << instr_name << " " << state.getIdName(inst->id()) - << "' must be a pointer to an OpTypeStruct."; + << " must be a pointer to an OpTypeStruct."; } auto num_of_members = structure_type->operands().size() - 1; @@ -1404,17 +1453,17 @@ spv_result_t ValidateArrayLength(ValidationState_t& state, state.FindDef(structure_type->GetOperandAs(num_of_members)); if (last_member->opcode() != SpvOpTypeRuntimeArray) { return state.diag(SPV_ERROR_INVALID_ID, inst) - << "The Struture's last member in " << instr_name << " '" - << state.getIdName(inst->id()) << "' must be an OpTypeRuntimeArray."; + << "The Structure's last member in " << instr_name << " " + << state.getIdName(inst->id()) << " must be an OpTypeRuntimeArray."; } // The array member must the index of the last element (the run time // array). if (inst->GetOperandAs(3) != num_of_members - 1) { return state.diag(SPV_ERROR_INVALID_ID, inst) - << "The array member in " << instr_name << " '" + << "The array member in " << instr_name << " " << state.getIdName(inst->id()) - << "' must be an the last member of the struct."; + << " must be an the last member of the struct."; } return SPV_SUCCESS; } @@ -1430,18 +1479,17 @@ spv_result_t ValidateCooperativeMatrixLengthNV(ValidationState_t& state, result_type->GetOperandAs(1) != 32 || result_type->GetOperandAs(2) != 0) { return state.diag(SPV_ERROR_INVALID_ID, inst) - << "The Result Type of " << instr_name << " '" + << "The Result Type of " << instr_name << " " << state.getIdName(inst->id()) - << "' must be OpTypeInt with width 32 and signedness 0."; + << " must be OpTypeInt with width 32 and signedness 0."; } auto type_id = inst->GetOperandAs(2); auto type = state.FindDef(type_id); if (type->opcode() != SpvOpTypeCooperativeMatrixNV) { return state.diag(SPV_ERROR_INVALID_ID, inst) - << "The type in " << instr_name << " '" - << state.getIdName(type_id) - << "' must be OpTypeCooperativeMatrixNV."; + << "The type in " << instr_name << " " + << state.getIdName(type_id) << " must be OpTypeCooperativeMatrixNV."; } return SPV_SUCCESS; } @@ -1464,12 +1512,12 @@ spv_result_t ValidateCooperativeMatrixLoadStoreNV(ValidationState_t& _, if (matrix_type->opcode() != SpvOpTypeCooperativeMatrixNV) { if (inst->opcode() == SpvOpCooperativeMatrixLoadNV) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "SpvOpCooperativeMatrixLoadNV Result Type '" - << _.getIdName(type_id) << "' is not a cooperative matrix type."; + << "SpvOpCooperativeMatrixLoadNV Result Type " + << _.getIdName(type_id) << " is not a cooperative matrix type."; } else { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "SpvOpCooperativeMatrixStoreNV Object type '" - << _.getIdName(type_id) << "' is not a cooperative matrix type."; + << "SpvOpCooperativeMatrixStoreNV Object type " + << _.getIdName(type_id) << " is not a cooperative matrix type."; } } @@ -1484,16 +1532,16 @@ spv_result_t ValidateCooperativeMatrixLoadStoreNV(ValidationState_t& _, (_.features().variable_pointers && !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opname << " Pointer '" << _.getIdName(pointer_id) - << "' is not a logical pointer."; + << 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() != SpvOpTypePointer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opname << " type for pointer '" << _.getIdName(pointer_id) - << "' is not a pointer type."; + << opname << " type for pointer " << _.getIdName(pointer_id) + << " is not a pointer type."; } const auto storage_class_index = 1u; @@ -1504,9 +1552,9 @@ spv_result_t ValidateCooperativeMatrixLoadStoreNV(ValidationState_t& _, storage_class != SpvStorageClassStorageBuffer && storage_class != SpvStorageClassPhysicalStorageBuffer) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opname << " storage class for pointer type '" + << opname << " storage class for pointer type " << _.getIdName(pointer_type_id) - << "' is not Workgroup or StorageBuffer."; + << " is not Workgroup or StorageBuffer."; } const auto pointee_id = pointer_type->GetOperandAs(2); @@ -1514,8 +1562,8 @@ spv_result_t ValidateCooperativeMatrixLoadStoreNV(ValidationState_t& _, if (!pointee_type || !(_.IsIntScalarOrVectorType(pointee_id) || _.IsFloatScalarOrVectorType(pointee_id))) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << opname << " Pointer '" << _.getIdName(pointer->id()) - << "'s Type must be a scalar or vector type."; + << opname << " Pointer " << _.getIdName(pointer->id()) + << "s Type must be a scalar or vector type."; } const auto stride_index = @@ -1524,8 +1572,8 @@ spv_result_t ValidateCooperativeMatrixLoadStoreNV(ValidationState_t& _, const auto stride = _.FindDef(stride_id); if (!stride || !_.IsIntScalarType(stride->type_id())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Stride operand '" << _.getIdName(stride_id) - << "' must be a scalar integer type."; + << "Stride operand " << _.getIdName(stride_id) + << " must be a scalar integer type."; } const auto colmajor_index = @@ -1536,8 +1584,8 @@ spv_result_t ValidateCooperativeMatrixLoadStoreNV(ValidationState_t& _, !(spvOpcodeIsConstant(colmajor->opcode()) || spvOpcodeIsSpecConstant(colmajor->opcode()))) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "Column Major operand '" << _.getIdName(colmajor_id) - << "' must be a boolean constant instruction."; + << "Column Major operand " << _.getIdName(colmajor_id) + << " must be a boolean constant instruction."; } const auto memory_access_index = diff --git a/3rdparty/spirv-tools/source/val/validate_mesh_shading.cpp b/3rdparty/spirv-tools/source/val/validate_mesh_shading.cpp new file mode 100644 index 000000000..a7f072672 --- /dev/null +++ b/3rdparty/spirv-tools/source/val/validate_mesh_shading.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2022 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Validates ray query instructions from SPV_KHR_ray_query + +#include "source/opcode.h" +#include "source/val/instruction.h" +#include "source/val/validate.h" +#include "source/val/validation_state.h" + +namespace spvtools { +namespace val { + +spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + switch (opcode) { + case SpvOpEmitMeshTasksEXT: { + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelTaskEXT) { + if (message) { + *message = + "OpEmitMeshTasksEXT requires TaskEXT execution model"; + } + return false; + } + return true; + }); + + const uint32_t group_count_x = _.GetOperandTypeId(inst, 0); + if (!_.IsUnsignedIntScalarType(group_count_x) || + _.GetBitWidth(group_count_x) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Group Count X must be a 32-bit unsigned int scalar"; + } + + const uint32_t group_count_y = _.GetOperandTypeId(inst, 1); + if (!_.IsUnsignedIntScalarType(group_count_y) || + _.GetBitWidth(group_count_y) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Group Count Y must be a 32-bit unsigned int scalar"; + } + + const uint32_t group_count_z = _.GetOperandTypeId(inst, 2); + if (!_.IsUnsignedIntScalarType(group_count_z) || + _.GetBitWidth(group_count_z) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Group Count Z must be a 32-bit unsigned int scalar"; + } + + if (inst->operands().size() == 4) { + const auto payload = _.FindDef(inst->GetOperandAs(3)); + if (payload->opcode() != SpvOpVariable) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Payload must be the result of a OpVariable"; + } + if (SpvStorageClass(payload->GetOperandAs(2)) != + SpvStorageClassTaskPayloadWorkgroupEXT) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Payload OpVariable must have a storage class of " + "TaskPayloadWorkgroupEXT"; + } + } + break; + } + + case SpvOpSetMeshOutputsEXT: { + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelMeshEXT) { + if (message) { + *message = + "OpSetMeshOutputsEXT requires MeshEXT execution model"; + } + return false; + } + return true; + }); + + const uint32_t vertex_count = _.GetOperandTypeId(inst, 0); + if (!_.IsUnsignedIntScalarType(vertex_count) || + _.GetBitWidth(vertex_count) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Vertex Count must be a 32-bit unsigned int scalar"; + } + + const uint32_t primitive_count = _.GetOperandTypeId(inst, 1); + if (!_.IsUnsignedIntScalarType(primitive_count) || + _.GetBitWidth(primitive_count) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Primitive Count must be a 32-bit unsigned int scalar"; + } + + break; + } + + case SpvOpWritePackedPrimitiveIndices4x8NV: { + // No validation rules (for the moment). + break; + } + + default: + break; + } + + return SPV_SUCCESS; +} + +} // namespace val +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp b/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp index 67b10c5ac..672192b9c 100644 --- a/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp +++ b/3rdparty/spirv-tools/source/val/validate_mode_setting.cpp @@ -12,13 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#include "source/val/validate.h" - #include #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 { @@ -30,8 +29,8 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) { auto entry_point = _.FindDef(entry_point_id); if (!entry_point || SpvOpFunction != entry_point->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpEntryPoint Entry Point '" << _.getIdName(entry_point_id) - << "' is not a function."; + << "OpEntryPoint Entry Point " << _.getIdName(entry_point_id) + << " is not a function."; } // Only check the shader execution models @@ -42,18 +41,18 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) { const auto entry_point_type = _.FindDef(entry_point_type_id); if (!entry_point_type || 3 != entry_point_type->words().size()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4633) << "OpEntryPoint Entry Point '" + << _.VkErrorID(4633) << "OpEntryPoint Entry Point " << _.getIdName(entry_point_id) - << "'s function parameter count is not zero."; + << "s function parameter count is not zero."; } } auto return_type = _.FindDef(entry_point->type_id()); if (!return_type || SpvOpTypeVoid != return_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4633) << "OpEntryPoint Entry Point '" + << _.VkErrorID(4633) << "OpEntryPoint Entry Point " << _.getIdName(entry_point_id) - << "'s function return type is not void."; + << "s function return type is not void."; } const auto* execution_modes = _.GetExecutionModes(entry_point_id); @@ -242,6 +241,39 @@ spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) { "OutputTriangleStrip execution modes."; } break; + case SpvExecutionModelMeshEXT: + if (!execution_modes || + 1 != std::count_if(execution_modes->begin(), execution_modes->end(), + [](const SpvExecutionMode& mode) { + switch (mode) { + case SpvExecutionModeOutputPoints: + case SpvExecutionModeOutputLinesEXT: + case SpvExecutionModeOutputTrianglesEXT: + return true; + default: + return false; + } + })) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "MeshEXT execution model entry points must specify exactly " + "one of OutputPoints, OutputLinesEXT, or " + "OutputTrianglesEXT Execution Modes."; + } else if (2 != std::count_if( + execution_modes->begin(), execution_modes->end(), + [](const SpvExecutionMode& mode) { + switch (mode) { + case SpvExecutionModeOutputPrimitivesEXT: + case SpvExecutionModeOutputVertices: + return true; + default: + return false; + } + })) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "MeshEXT execution model entry points must specify both " + "OutputPrimitivesEXT and OutputVertices Execution Modes."; + } + break; default: break; } @@ -296,9 +328,8 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, _.entry_points().cend(), entry_point_id); if (found == _.entry_points().cend()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpExecutionMode Entry Point '" - << _.getIdName(entry_point_id) - << "' is not the Entry Point " + << "OpExecutionMode Entry Point " << _.getIdName(entry_point_id) + << " is not the Entry Point " "operand of an OpEntryPoint."; } @@ -359,14 +390,18 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, return true; case SpvExecutionModelMeshNV: return _.HasCapability(SpvCapabilityMeshShadingNV); + case SpvExecutionModelMeshEXT: + return _.HasCapability( + SpvCapabilityMeshShadingEXT); default: return false; } })) { - if (_.HasCapability(SpvCapabilityMeshShadingNV)) { + if (_.HasCapability(SpvCapabilityMeshShadingNV) || + _.HasCapability(SpvCapabilityMeshShadingEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) - << "Execution mode can only be used with the Geometry or " - "MeshNV execution model."; + << "Execution mode can only be used with the Geometry " + "MeshNV or MeshEXT execution model."; } else { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with the Geometry " @@ -421,14 +456,18 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, return true; case SpvExecutionModelMeshNV: return _.HasCapability(SpvCapabilityMeshShadingNV); + case SpvExecutionModelMeshEXT: + return _.HasCapability( + SpvCapabilityMeshShadingEXT); default: return false; } })) { - if (_.HasCapability(SpvCapabilityMeshShadingNV)) { + if (_.HasCapability(SpvCapabilityMeshShadingNV) || + _.HasCapability(SpvCapabilityMeshShadingEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Geometry, " - "tessellation or MeshNV execution model."; + "tessellation, MeshNV or MeshEXT execution model."; } else { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Geometry or " @@ -436,6 +475,20 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, } } break; + case SpvExecutionModeOutputLinesEXT: + case SpvExecutionModeOutputTrianglesEXT: + case SpvExecutionModeOutputPrimitivesEXT: + if (!std::all_of(models->begin(), models->end(), + [](const SpvExecutionModel& model) { + return (model == SpvExecutionModelMeshEXT || + model == SpvExecutionModelMeshNV); + })) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Execution mode can only be used with the MeshEXT or MeshNV " + "execution " + "model."; + } + break; case SpvExecutionModePixelCenterInteger: case SpvExecutionModeOriginUpperLeft: case SpvExecutionModeOriginLowerLeft: @@ -494,14 +547,19 @@ spv_result_t ValidateExecutionMode(ValidationState_t& _, case SpvExecutionModelTaskNV: case SpvExecutionModelMeshNV: return _.HasCapability(SpvCapabilityMeshShadingNV); + case SpvExecutionModelTaskEXT: + case SpvExecutionModelMeshEXT: + return _.HasCapability( + SpvCapabilityMeshShadingEXT); default: return false; } })) { - if (_.HasCapability(SpvCapabilityMeshShadingNV)) { + if (_.HasCapability(SpvCapabilityMeshShadingNV) || + _.HasCapability(SpvCapabilityMeshShadingEXT)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Kernel, GLCompute, " - "MeshNV, or TaskNV execution model."; + "MeshNV, MeshEXT, TaskNV or TaskEXT execution model."; } else { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Execution mode can only be used with a Kernel or " diff --git a/3rdparty/spirv-tools/source/val/validate_ray_query.cpp b/3rdparty/spirv-tools/source/val/validate_ray_query.cpp index f92bf016a..b553449d0 100644 --- a/3rdparty/spirv-tools/source/val/validate_ray_query.cpp +++ b/3rdparty/spirv-tools/source/val/validate_ray_query.cpp @@ -28,8 +28,10 @@ spv_result_t ValidateRayQueryPointer(ValidationState_t& _, uint32_t ray_query_index) { const uint32_t ray_query_id = inst->GetOperandAs(ray_query_index); auto variable = _.FindDef(ray_query_id); - if (!variable || (variable->opcode() != SpvOpVariable && - variable->opcode() != SpvOpFunctionParameter)) { + const auto var_opcode = variable->opcode(); + if (!variable || + (var_opcode != SpvOpVariable && var_opcode != SpvOpFunctionParameter && + var_opcode != SpvOpAccessChain)) { return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Ray Query must be a memory object declaration"; } diff --git a/3rdparty/spirv-tools/source/val/validate_ray_tracing.cpp b/3rdparty/spirv-tools/source/val/validate_ray_tracing.cpp new file mode 100644 index 000000000..5b5c8da1e --- /dev/null +++ b/3rdparty/spirv-tools/source/val/validate_ray_tracing.cpp @@ -0,0 +1,209 @@ +// Copyright (c) 2022 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Validates ray tracing instructions from SPV_KHR_ray_tracing + +#include "source/opcode.h" +#include "source/val/instruction.h" +#include "source/val/validate.h" +#include "source/val/validation_state.h" + +namespace spvtools { +namespace val { + +spv_result_t RayTracingPass(ValidationState_t& _, const Instruction* inst) { + const SpvOp opcode = inst->opcode(); + const uint32_t result_type = inst->type_id(); + + switch (opcode) { + case SpvOpTraceRayKHR: { + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = + "OpTraceRayKHR requires RayGenerationKHR, " + "ClosestHitKHR and MissKHR execution models"; + } + return false; + } + return true; + }); + + if (_.GetIdOpcode(_.GetOperandTypeId(inst, 0)) != + SpvOpTypeAccelerationStructureKHR) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Expected Acceleration Structure to be of type " + "OpTypeAccelerationStructureKHR"; + } + + const uint32_t ray_flags = _.GetOperandTypeId(inst, 1); + if (!_.IsIntScalarType(ray_flags) || _.GetBitWidth(ray_flags) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Ray Flags must be a 32-bit int scalar"; + } + + const uint32_t cull_mask = _.GetOperandTypeId(inst, 2); + if (!_.IsIntScalarType(cull_mask) || _.GetBitWidth(cull_mask) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Cull Mask must be a 32-bit int scalar"; + } + + const uint32_t sbt_offset = _.GetOperandTypeId(inst, 3); + if (!_.IsIntScalarType(sbt_offset) || _.GetBitWidth(sbt_offset) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "SBT Offset must be a 32-bit int scalar"; + } + + const uint32_t sbt_stride = _.GetOperandTypeId(inst, 4); + if (!_.IsIntScalarType(sbt_stride) || _.GetBitWidth(sbt_stride) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "SBT Stride must be a 32-bit int scalar"; + } + + const uint32_t miss_index = _.GetOperandTypeId(inst, 5); + if (!_.IsIntScalarType(miss_index) || _.GetBitWidth(miss_index) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Miss Index must be a 32-bit int scalar"; + } + + const uint32_t ray_origin = _.GetOperandTypeId(inst, 6); + if (!_.IsFloatVectorType(ray_origin) || _.GetDimension(ray_origin) != 3 || + _.GetBitWidth(ray_origin) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Ray Origin must be a 32-bit float 3-component vector"; + } + + const uint32_t ray_tmin = _.GetOperandTypeId(inst, 7); + if (!_.IsFloatScalarType(ray_tmin) || _.GetBitWidth(ray_tmin) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Ray TMin must be a 32-bit float scalar"; + } + + const uint32_t ray_direction = _.GetOperandTypeId(inst, 8); + if (!_.IsFloatVectorType(ray_direction) || + _.GetDimension(ray_direction) != 3 || + _.GetBitWidth(ray_direction) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Ray Direction must be a 32-bit float 3-component vector"; + } + + const uint32_t ray_tmax = _.GetOperandTypeId(inst, 9); + if (!_.IsFloatScalarType(ray_tmax) || _.GetBitWidth(ray_tmax) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Ray TMax must be a 32-bit float scalar"; + } + + const Instruction* payload = _.FindDef(inst->GetOperandAs(10)); + if (payload->opcode() != SpvOpVariable) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Payload must be the result of a OpVariable"; + } else if (payload->GetOperandAs(2) != + SpvStorageClassRayPayloadKHR && + payload->GetOperandAs(2) != + SpvStorageClassIncomingRayPayloadKHR) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Payload must have storage class RayPayloadKHR or " + "IncomingRayPayloadKHR"; + } + break; + } + + case SpvOpReportIntersectionKHR: { + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelIntersectionKHR) { + if (message) { + *message = + "OpReportIntersectionKHR requires IntersectionKHR " + "execution model"; + } + return false; + } + return true; + }); + + if (!_.IsBoolScalarType(result_type)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "expected Result Type to be bool scalar type"; + } + + const uint32_t hit = _.GetOperandTypeId(inst, 2); + if (!_.IsFloatScalarType(hit) || _.GetBitWidth(hit) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Hit must be a 32-bit int scalar"; + } + + const uint32_t hit_kind = _.GetOperandTypeId(inst, 3); + if (!_.IsUnsignedIntScalarType(hit_kind) || + _.GetBitWidth(hit_kind) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Hit Kind must be a 32-bit unsigned int scalar"; + } + break; + } + + case SpvOpExecuteCallableKHR: { + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation([](SpvExecutionModel model, + std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelMissKHR && + model != SpvExecutionModelCallableKHR) { + if (message) { + *message = + "OpExecuteCallableKHR requires RayGenerationKHR, " + "ClosestHitKHR, MissKHR and CallableKHR execution models"; + } + return false; + } + return true; + }); + + const uint32_t sbt_index = _.GetOperandTypeId(inst, 0); + if (!_.IsUnsignedIntScalarType(sbt_index) || + _.GetBitWidth(sbt_index) != 32) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "SBT Index must be a 32-bit unsigned int scalar"; + } + + const auto callable_data = _.FindDef(inst->GetOperandAs(1)); + if (callable_data->opcode() != SpvOpVariable) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Callable Data must be the result of a OpVariable"; + } else if (callable_data->GetOperandAs(2) != + SpvStorageClassCallableDataKHR && + callable_data->GetOperandAs(2) != + SpvStorageClassIncomingCallableDataKHR) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Callable Data must have storage class CallableDataKHR or " + "IncomingCallableDataKHR"; + } + + break; + } + + default: + break; + } + + return SPV_SUCCESS; +} +} // namespace val +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/val/validate_scopes.cpp b/3rdparty/spirv-tools/source/val/validate_scopes.cpp index a5f3db14f..e9781802c 100644 --- a/3rdparty/spirv-tools/source/val/validate_scopes.cpp +++ b/3rdparty/spirv-tools/source/val/validate_scopes.cpp @@ -144,14 +144,16 @@ spv_result_t ValidateExecutionScope(ValidationState_t& _, [errorVUID](SpvExecutionModel model, std::string* message) { if (model != SpvExecutionModelTaskNV && model != SpvExecutionModelMeshNV && + model != SpvExecutionModelTaskEXT && + model != SpvExecutionModelMeshEXT && model != SpvExecutionModelTessellationControl && model != SpvExecutionModelGLCompute) { if (message) { *message = errorVUID + "in Vulkan environment, Workgroup execution scope is " - "only for TaskNV, MeshNV, TessellationControl, and " - "GLCompute execution models"; + "only for TaskNV, MeshNV, TaskEXT, MeshEXT, " + "TessellationControl, and GLCompute execution models"; } return false; } @@ -263,22 +265,44 @@ spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst, } if (value == SpvScopeWorkgroup) { - std::string errorVUID = _.VkErrorID(4639); + std::string errorVUID = _.VkErrorID(7321); _.function(inst->function()->id()) ->RegisterExecutionModelLimitation( [errorVUID](SpvExecutionModel model, std::string* message) { if (model != SpvExecutionModelGLCompute && + model != SpvExecutionModelTessellationControl && model != SpvExecutionModelTaskNV && - model != SpvExecutionModelMeshNV) { + model != SpvExecutionModelMeshNV && + model != SpvExecutionModelTaskEXT && + model != SpvExecutionModelMeshEXT) { if (message) { *message = errorVUID + "Workgroup Memory Scope is limited to MeshNV, " - "TaskNV, and GLCompute execution model"; + "TaskNV, MeshEXT, TaskEXT, TessellationControl, " + "and GLCompute execution model"; } return false; } return true; }); + + if (_.memory_model() == SpvMemoryModelGLSL450) { + errorVUID = _.VkErrorID(7320); + _.function(inst->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model == SpvExecutionModelTessellationControl) { + if (message) { + *message = + errorVUID + + "Workgroup Memory Scope can't be used with " + "TessellationControl using GLSL450 Memory Model"; + } + return false; + } + return true; + }); + } } } diff --git a/3rdparty/spirv-tools/source/val/validate_type.cpp b/3rdparty/spirv-tools/source/val/validate_type.cpp index b0b60792b..6b0881cf8 100644 --- a/3rdparty/spirv-tools/source/val/validate_type.cpp +++ b/3rdparty/spirv-tools/source/val/validate_type.cpp @@ -152,8 +152,8 @@ spv_result_t ValidateTypeVector(ValidationState_t& _, const Instruction* inst) { const auto component_type = _.FindDef(component_id); if (!component_type || !spvOpcodeIsScalarType(component_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeVector Component Type '" << _.getIdName(component_id) - << "' is not a scalar type."; + << "OpTypeVector Component Type " << _.getIdName(component_id) + << " is not a scalar type."; } // Validates that the number of components in the vector is valid. @@ -215,21 +215,21 @@ spv_result_t ValidateTypeArray(ValidationState_t& _, const Instruction* inst) { const auto element_type = _.FindDef(element_type_id); if (!element_type || !spvOpcodeGeneratesType(element_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeArray Element Type '" << _.getIdName(element_type_id) - << "' is not a type."; + << "OpTypeArray Element Type " << _.getIdName(element_type_id) + << " is not a type."; } if (element_type->opcode() == SpvOpTypeVoid) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeArray Element Type '" << _.getIdName(element_type_id) - << "' is a void type."; + << "OpTypeArray Element Type " << _.getIdName(element_type_id) + << " is a void type."; } if (spvIsVulkanEnv(_.context()->target_env) && element_type->opcode() == SpvOpTypeRuntimeArray) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4680) << "OpTypeArray Element Type '" - << _.getIdName(element_type_id) << "' is not valid in " + << _.VkErrorID(4680) << "OpTypeArray Element Type " + << _.getIdName(element_type_id) << " is not valid in " << spvLogStringForEnv(_.context()->target_env) << " environments."; } @@ -238,8 +238,8 @@ spv_result_t ValidateTypeArray(ValidationState_t& _, const Instruction* inst) { const auto length = _.FindDef(length_id); if (!length || !spvOpcodeIsConstant(length->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeArray Length '" << _.getIdName(length_id) - << "' is not a scalar constant type."; + << "OpTypeArray Length " << _.getIdName(length_id) + << " is not a scalar constant type."; } // NOTE: Check the initialiser value of the constant @@ -248,8 +248,8 @@ spv_result_t ValidateTypeArray(ValidationState_t& _, const Instruction* inst) { const auto const_result_type = _.FindDef(const_inst[const_result_type_index]); if (!const_result_type || SpvOpTypeInt != const_result_type->opcode()) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeArray Length '" << _.getIdName(length_id) - << "' is not a constant integer type."; + << "OpTypeArray Length " << _.getIdName(length_id) + << " is not a constant integer type."; } switch (length->opcode()) { @@ -261,14 +261,14 @@ spv_result_t ValidateTypeArray(ValidationState_t& _, const Instruction* inst) { const int64_t ivalue = ConstantLiteralAsInt64(width, length->words()); if (ivalue == 0 || (ivalue < 0 && is_signed)) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeArray Length '" << _.getIdName(length_id) - << "' default value must be at least 1: found " << ivalue; + << "OpTypeArray Length " << _.getIdName(length_id) + << " default value must be at least 1: found " << ivalue; } } break; case SpvOpConstantNull: return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeArray Length '" << _.getIdName(length_id) - << "' default value must be at least 1."; + << "OpTypeArray Length " << _.getIdName(length_id) + << " default value must be at least 1."; case SpvOpSpecConstantOp: // Assume it's OK, rather than try to evaluate the operation. break; @@ -285,21 +285,21 @@ spv_result_t ValidateTypeRuntimeArray(ValidationState_t& _, const auto element_type = _.FindDef(element_id); if (!element_type || !spvOpcodeGeneratesType(element_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeRuntimeArray Element Type '" - << _.getIdName(element_id) << "' is not a type."; + << "OpTypeRuntimeArray Element Type " << _.getIdName(element_id) + << " is not a type."; } if (element_type->opcode() == SpvOpTypeVoid) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeRuntimeArray Element Type '" - << _.getIdName(element_id) << "' is a void type."; + << "OpTypeRuntimeArray Element Type " << _.getIdName(element_id) + << " is a void type."; } if (spvIsVulkanEnv(_.context()->target_env) && element_type->opcode() == SpvOpTypeRuntimeArray) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << _.VkErrorID(4680) << "OpTypeRuntimeArray Element Type '" - << _.getIdName(element_id) << "' is not valid in " + << _.VkErrorID(4680) << "OpTypeRuntimeArray Element Type " + << _.getIdName(element_id) << " is not valid in " << spvLogStringForEnv(_.context()->target_env) << " environments."; } @@ -319,8 +319,8 @@ spv_result_t ValidateTypeStruct(ValidationState_t& _, const Instruction* inst) { auto member_type = _.FindDef(member_type_id); if (!member_type || !spvOpcodeGeneratesType(member_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeStruct Member Type '" << _.getIdName(member_type_id) - << "' is not a type."; + << "OpTypeStruct Member Type " << _.getIdName(member_type_id) + << " is not a type."; } if (member_type->opcode() == SpvOpTypeVoid) { return _.diag(SPV_ERROR_INVALID_ID, inst) @@ -426,8 +426,8 @@ spv_result_t ValidateTypePointer(ValidationState_t& _, auto type = _.FindDef(type_id); if (!type || !spvOpcodeGeneratesType(type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypePointer Type '" << _.getIdName(type_id) - << "' is not a type."; + << "OpTypePointer Type " << _.getIdName(type_id) + << " is not a type."; } // See if this points to a storage image. const auto storage_class = inst->GetOperandAs(1); @@ -461,8 +461,8 @@ spv_result_t ValidateTypeFunction(ValidationState_t& _, const auto return_type = _.FindDef(return_type_id); if (!return_type || !spvOpcodeGeneratesType(return_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeFunction Return Type '" << _.getIdName(return_type_id) - << "' is not a type."; + << "OpTypeFunction Return Type " << _.getIdName(return_type_id) + << " is not a type."; } size_t num_args = 0; for (size_t param_type_index = 2; param_type_index < inst->operands().size(); @@ -471,14 +471,14 @@ spv_result_t ValidateTypeFunction(ValidationState_t& _, const auto param_type = _.FindDef(param_id); if (!param_type || !spvOpcodeGeneratesType(param_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeFunction Parameter Type '" << _.getIdName(param_id) - << "' is not a type."; + << "OpTypeFunction Parameter Type " << _.getIdName(param_id) + << " is not a type."; } if (param_type->opcode() == SpvOpTypeVoid) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeFunction Parameter Type '" << _.getIdName(param_id) - << "' cannot be OpTypeVoid."; + << "OpTypeFunction Parameter Type " << _.getIdName(param_id) + << " cannot be OpTypeVoid."; } } const uint32_t num_function_args_limit = @@ -486,8 +486,8 @@ spv_result_t ValidateTypeFunction(ValidationState_t& _, if (num_args > num_function_args_limit) { return _.diag(SPV_ERROR_INVALID_ID, inst) << "OpTypeFunction may not take more than " - << num_function_args_limit << " arguments. OpTypeFunction '" - << _.getIdName(inst->GetOperandAs(0)) << "' has " + << num_function_args_limit << " arguments. OpTypeFunction " + << _.getIdName(inst->GetOperandAs(0)) << " has " << num_args << " arguments."; } @@ -550,9 +550,9 @@ spv_result_t ValidateTypeCooperativeMatrixNV(ValidationState_t& _, if (!component_type || (SpvOpTypeFloat != component_type->opcode() && SpvOpTypeInt != component_type->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeCooperativeMatrixNV Component Type '" + << "OpTypeCooperativeMatrixNV Component Type " << _.getIdName(component_type_id) - << "' is not a scalar numerical type."; + << " is not a scalar numerical type."; } const auto scope_index = 2; @@ -561,8 +561,8 @@ spv_result_t ValidateTypeCooperativeMatrixNV(ValidationState_t& _, if (!scope || !_.IsIntScalarType(scope->type_id()) || !spvOpcodeIsConstant(scope->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeCooperativeMatrixNV Scope '" << _.getIdName(scope_id) - << "' is not a constant instruction with scalar integer type."; + << "OpTypeCooperativeMatrixNV Scope " << _.getIdName(scope_id) + << " is not a constant instruction with scalar integer type."; } const auto rows_index = 3; @@ -571,8 +571,8 @@ spv_result_t ValidateTypeCooperativeMatrixNV(ValidationState_t& _, if (!rows || !_.IsIntScalarType(rows->type_id()) || !spvOpcodeIsConstant(rows->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeCooperativeMatrixNV Rows '" << _.getIdName(rows_id) - << "' is not a constant instruction with scalar integer type."; + << "OpTypeCooperativeMatrixNV Rows " << _.getIdName(rows_id) + << " is not a constant instruction with scalar integer type."; } const auto cols_index = 4; @@ -581,8 +581,8 @@ spv_result_t ValidateTypeCooperativeMatrixNV(ValidationState_t& _, if (!cols || !_.IsIntScalarType(cols->type_id()) || !spvOpcodeIsConstant(cols->opcode())) { return _.diag(SPV_ERROR_INVALID_ID, inst) - << "OpTypeCooperativeMatrixNV Cols '" << _.getIdName(cols_id) - << "' is not a constant instruction with scalar integer type."; + << "OpTypeCooperativeMatrixNV Cols " << _.getIdName(cols_id) + << " is not a constant instruction with scalar integer type."; } return SPV_SUCCESS; diff --git a/3rdparty/spirv-tools/source/val/validation_state.cpp b/3rdparty/spirv-tools/source/val/validation_state.cpp index 2702b2b08..d5ddc9c10 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.cpp +++ b/3rdparty/spirv-tools/source/val/validation_state.cpp @@ -208,9 +208,12 @@ ValidationState_t::ValidationState_t(const spv_const_context ctx, } UpdateFeaturesBasedOnSpirvVersion(&features_, version_); - friendly_mapper_ = spvtools::MakeUnique( - context_, words_, num_words_); - name_mapper_ = friendly_mapper_->GetNameMapper(); + name_mapper_ = spvtools::GetTrivialNameMapper(); + if (options_->use_friendly_names) { + friendly_mapper_ = spvtools::MakeUnique( + context_, words_, num_words_); + name_mapper_ = friendly_mapper_->GetNameMapper(); + } } void ValidationState_t::preallocateStorage() { @@ -245,7 +248,7 @@ std::string ValidationState_t::getIdName(uint32_t id) const { const std::string id_name = name_mapper_(id); std::stringstream out; - out << id << "[%" << id_name << "]"; + out << "'" << id << "[%" << id_name << "]'"; return out.str(); } @@ -608,7 +611,8 @@ void ValidationState_t::RegisterStorageClassConsumer( std::string errorVUID = VkErrorID(4644); function(consumer->function()->id()) ->RegisterExecutionModelLimitation([errorVUID]( - SpvExecutionModel model, std::string* message) { + SpvExecutionModel model, + std::string* message) { if (model == SpvExecutionModelGLCompute || model == SpvExecutionModelRayGenerationKHR || model == SpvExecutionModelIntersectionKHR || @@ -634,10 +638,13 @@ void ValidationState_t::RegisterStorageClassConsumer( std::string errorVUID = VkErrorID(4645); function(consumer->function()->id()) ->RegisterExecutionModelLimitation([errorVUID]( - SpvExecutionModel model, std::string* message) { + SpvExecutionModel model, + std::string* message) { if (model != SpvExecutionModelGLCompute && model != SpvExecutionModelTaskNV && - model != SpvExecutionModelMeshNV) { + model != SpvExecutionModelMeshNV && + model != SpvExecutionModelTaskEXT && + model != SpvExecutionModelMeshEXT) { if (message) { *message = errorVUID + @@ -650,6 +657,133 @@ void ValidationState_t::RegisterStorageClassConsumer( }); } } + + if (storage_class == SpvStorageClassCallableDataKHR) { + std::string errorVUID = VkErrorID(4704); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model, + std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelCallableKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = errorVUID + + "CallableDataKHR Storage Class is limited to " + "RayGenerationKHR, ClosestHitKHR, CallableKHR, and " + "MissKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassIncomingCallableDataKHR) { + std::string errorVUID = VkErrorID(4705); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model, + std::string* message) { + if (model != SpvExecutionModelCallableKHR) { + if (message) { + *message = errorVUID + + "IncomingCallableDataKHR Storage Class is limited to " + "CallableKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassRayPayloadKHR) { + std::string errorVUID = VkErrorID(4698); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model, + std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = + errorVUID + + "RayPayloadKHR Storage Class is limited to RayGenerationKHR, " + "ClosestHitKHR, and MissKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassHitAttributeKHR) { + std::string errorVUID = VkErrorID(4701); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelIntersectionKHR && + model != SpvExecutionModelAnyHitKHR && + model != SpvExecutionModelClosestHitKHR) { + if (message) { + *message = errorVUID + + "HitAttributeKHR Storage Class is limited to " + "IntersectionKHR, AnyHitKHR, sand ClosestHitKHR " + "execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassIncomingRayPayloadKHR) { + std::string errorVUID = VkErrorID(4699); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelAnyHitKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = + errorVUID + + "IncomingRayPayloadKHR Storage Class is limited to " + "AnyHitKHR, ClosestHitKHR, and MissKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassShaderRecordBufferKHR) { + std::string errorVUID = VkErrorID(7119); + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation( + [errorVUID](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelRayGenerationKHR && + model != SpvExecutionModelIntersectionKHR && + model != SpvExecutionModelAnyHitKHR && + model != SpvExecutionModelClosestHitKHR && + model != SpvExecutionModelCallableKHR && + model != SpvExecutionModelMissKHR) { + if (message) { + *message = + errorVUID + + "ShaderRecordBufferKHR Storage Class is limited to " + "RayGenerationKHR, IntersectionKHR, AnyHitKHR, " + "ClosestHitKHR, CallableKHR, and MissKHR execution model"; + } + return false; + } + return true; + }); + } else if (storage_class == SpvStorageClassTaskPayloadWorkgroupEXT) { + function(consumer->function()->id()) + ->RegisterExecutionModelLimitation( + [](SpvExecutionModel model, std::string* message) { + if (model != SpvExecutionModelTaskEXT && + model != SpvExecutionModelMeshEXT) { + if (message) { + *message = + "TaskPayloadWorkgroupEXT Storage Class is limited to " + "TaskEXT and MeshKHR execution model"; + } + return false; + } + return true; + }); + } } uint32_t ValidationState_t::getIdBound() const { return id_bound_; } @@ -1410,6 +1544,7 @@ bool ValidationState_t::IsValidStorageClass( case SpvStorageClassCallableDataKHR: case SpvStorageClassIncomingCallableDataKHR: case SpvStorageClassShaderRecordBufferKHR: + case SpvStorageClassTaskPayloadWorkgroupEXT: return true; default: return false; @@ -1853,8 +1988,8 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-StandaloneSpirv-None-04637); case 4638: return VUID_WRAP(VUID-StandaloneSpirv-None-04638); - case 4639: - return VUID_WRAP(VUID-StandaloneSpirv-None-04639); + case 7321: + return VUID_WRAP(VUID-StandaloneSpirv-None-07321); case 4640: return VUID_WRAP(VUID-StandaloneSpirv-None-04640); case 4641: @@ -1911,6 +2046,20 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685); case 4686: return VUID_WRAP(VUID-StandaloneSpirv-None-04686); + case 4698: + return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698); + case 4699: + return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699); + case 4701: + return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701); + case 4703: + return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703); + case 4704: + return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704); + case 4705: + return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705); + case 7119: + return VUID_WRAP(VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119); case 4708: return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708); case 4710: @@ -1979,6 +2128,12 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925); case 6997: return VUID_WRAP(VUID-StandaloneSpirv-SubgroupVoteKHR-06997); + case 7102: + return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102); + case 7320: + return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320); + case 7290: + return VUID_WRAP(VUID-StandaloneSpirv-Input-07290); default: return ""; // unknown id } diff --git a/3rdparty/spirv-tools/source/val/validation_state.h b/3rdparty/spirv-tools/source/val/validation_state.h index b4d343d94..1b599ff35 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.h +++ b/3rdparty/spirv-tools/source/val/validation_state.h @@ -723,6 +723,16 @@ class ValidationState_t { // Returns the disassembly string for the given instruction. std::string Disassemble(const uint32_t* words, uint16_t num_words) const; + // Returns the string name for |decoration|. + std::string SpvDecorationString(uint32_t decoration) { + spv_operand_desc desc = nullptr; + if (grammar_.lookupOperand(SPV_OPERAND_TYPE_DECORATION, decoration, + &desc) != SPV_SUCCESS) { + return std::string("Unknown"); + } + return std::string(desc->name); + } + // 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.