mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-tools.
This commit is contained in:
@@ -1 +1 @@
|
||||
"v2022.5-dev", "SPIRV-Tools v2022.5-dev 01f246880b501c751d62ad543d886e08bfa756b5"
|
||||
"v2022.5-dev", "SPIRV-Tools v2022.5-dev 466c6a4e95f6c2ebd61040d6fe2f6418e45b7e20"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -78,6 +78,10 @@ const char* ExtensionToString(Extension extension) {
|
||||
return "SPV_INTEL_fpga_buffer_location";
|
||||
case Extension::kSPV_INTEL_fpga_cluster_attributes:
|
||||
return "SPV_INTEL_fpga_cluster_attributes";
|
||||
case Extension::kSPV_INTEL_fpga_dsp_control:
|
||||
return "SPV_INTEL_fpga_dsp_control";
|
||||
case Extension::kSPV_INTEL_fpga_invocation_pipelining_attributes:
|
||||
return "SPV_INTEL_fpga_invocation_pipelining_attributes";
|
||||
case Extension::kSPV_INTEL_fpga_loop_controls:
|
||||
return "SPV_INTEL_fpga_loop_controls";
|
||||
case Extension::kSPV_INTEL_fpga_memory_accesses:
|
||||
@@ -104,6 +108,8 @@ const char* ExtensionToString(Extension extension) {
|
||||
return "SPV_INTEL_memory_access_aliasing";
|
||||
case Extension::kSPV_INTEL_optnone:
|
||||
return "SPV_INTEL_optnone";
|
||||
case Extension::kSPV_INTEL_runtime_aligned:
|
||||
return "SPV_INTEL_runtime_aligned";
|
||||
case Extension::kSPV_INTEL_shader_integer_functions2:
|
||||
return "SPV_INTEL_shader_integer_functions2";
|
||||
case Extension::kSPV_INTEL_split_barrier:
|
||||
@@ -202,6 +208,8 @@ const char* ExtensionToString(Extension extension) {
|
||||
return "SPV_NV_sample_mask_override_coverage";
|
||||
case Extension::kSPV_NV_shader_image_footprint:
|
||||
return "SPV_NV_shader_image_footprint";
|
||||
case Extension::kSPV_NV_shader_invocation_reorder:
|
||||
return "SPV_NV_shader_invocation_reorder";
|
||||
case Extension::kSPV_NV_shader_sm_builtins:
|
||||
return "SPV_NV_shader_sm_builtins";
|
||||
case Extension::kSPV_NV_shader_subgroup_partitioned:
|
||||
@@ -221,8 +229,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_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_opacity_micromap", "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_opacity_micromap, 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_opacity_micromap", "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_dsp_control", "SPV_INTEL_fpga_invocation_pipelining_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_runtime_aligned", "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_invocation_reorder", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_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_opacity_micromap, 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_dsp_control, Extension::kSPV_INTEL_fpga_invocation_pipelining_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_runtime_aligned, 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_invocation_reorder, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_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(
|
||||
@@ -236,414 +244,422 @@ const char* ExtensionToString(Extension extension) {
|
||||
}
|
||||
|
||||
|
||||
const char* CapabilityToString(SpvCapability capability) {
|
||||
const char* CapabilityToString(spv::Capability capability) {
|
||||
switch (capability) {
|
||||
case SpvCapabilityMatrix:
|
||||
case spv::Capability::Matrix:
|
||||
return "Matrix";
|
||||
case SpvCapabilityShader:
|
||||
case spv::Capability::Shader:
|
||||
return "Shader";
|
||||
case SpvCapabilityGeometry:
|
||||
case spv::Capability::Geometry:
|
||||
return "Geometry";
|
||||
case SpvCapabilityTessellation:
|
||||
case spv::Capability::Tessellation:
|
||||
return "Tessellation";
|
||||
case SpvCapabilityAddresses:
|
||||
case spv::Capability::Addresses:
|
||||
return "Addresses";
|
||||
case SpvCapabilityLinkage:
|
||||
case spv::Capability::Linkage:
|
||||
return "Linkage";
|
||||
case SpvCapabilityKernel:
|
||||
case spv::Capability::Kernel:
|
||||
return "Kernel";
|
||||
case SpvCapabilityVector16:
|
||||
case spv::Capability::Vector16:
|
||||
return "Vector16";
|
||||
case SpvCapabilityFloat16Buffer:
|
||||
case spv::Capability::Float16Buffer:
|
||||
return "Float16Buffer";
|
||||
case SpvCapabilityFloat16:
|
||||
case spv::Capability::Float16:
|
||||
return "Float16";
|
||||
case SpvCapabilityFloat64:
|
||||
case spv::Capability::Float64:
|
||||
return "Float64";
|
||||
case SpvCapabilityInt64:
|
||||
case spv::Capability::Int64:
|
||||
return "Int64";
|
||||
case SpvCapabilityInt64Atomics:
|
||||
case spv::Capability::Int64Atomics:
|
||||
return "Int64Atomics";
|
||||
case SpvCapabilityImageBasic:
|
||||
case spv::Capability::ImageBasic:
|
||||
return "ImageBasic";
|
||||
case SpvCapabilityImageReadWrite:
|
||||
case spv::Capability::ImageReadWrite:
|
||||
return "ImageReadWrite";
|
||||
case SpvCapabilityImageMipmap:
|
||||
case spv::Capability::ImageMipmap:
|
||||
return "ImageMipmap";
|
||||
case SpvCapabilityPipes:
|
||||
case spv::Capability::Pipes:
|
||||
return "Pipes";
|
||||
case SpvCapabilityGroups:
|
||||
case spv::Capability::Groups:
|
||||
return "Groups";
|
||||
case SpvCapabilityDeviceEnqueue:
|
||||
case spv::Capability::DeviceEnqueue:
|
||||
return "DeviceEnqueue";
|
||||
case SpvCapabilityLiteralSampler:
|
||||
case spv::Capability::LiteralSampler:
|
||||
return "LiteralSampler";
|
||||
case SpvCapabilityAtomicStorage:
|
||||
case spv::Capability::AtomicStorage:
|
||||
return "AtomicStorage";
|
||||
case SpvCapabilityInt16:
|
||||
case spv::Capability::Int16:
|
||||
return "Int16";
|
||||
case SpvCapabilityTessellationPointSize:
|
||||
case spv::Capability::TessellationPointSize:
|
||||
return "TessellationPointSize";
|
||||
case SpvCapabilityGeometryPointSize:
|
||||
case spv::Capability::GeometryPointSize:
|
||||
return "GeometryPointSize";
|
||||
case SpvCapabilityImageGatherExtended:
|
||||
case spv::Capability::ImageGatherExtended:
|
||||
return "ImageGatherExtended";
|
||||
case SpvCapabilityStorageImageMultisample:
|
||||
case spv::Capability::StorageImageMultisample:
|
||||
return "StorageImageMultisample";
|
||||
case SpvCapabilityUniformBufferArrayDynamicIndexing:
|
||||
case spv::Capability::UniformBufferArrayDynamicIndexing:
|
||||
return "UniformBufferArrayDynamicIndexing";
|
||||
case SpvCapabilitySampledImageArrayDynamicIndexing:
|
||||
case spv::Capability::SampledImageArrayDynamicIndexing:
|
||||
return "SampledImageArrayDynamicIndexing";
|
||||
case SpvCapabilityStorageBufferArrayDynamicIndexing:
|
||||
case spv::Capability::StorageBufferArrayDynamicIndexing:
|
||||
return "StorageBufferArrayDynamicIndexing";
|
||||
case SpvCapabilityStorageImageArrayDynamicIndexing:
|
||||
case spv::Capability::StorageImageArrayDynamicIndexing:
|
||||
return "StorageImageArrayDynamicIndexing";
|
||||
case SpvCapabilityClipDistance:
|
||||
case spv::Capability::ClipDistance:
|
||||
return "ClipDistance";
|
||||
case SpvCapabilityCullDistance:
|
||||
case spv::Capability::CullDistance:
|
||||
return "CullDistance";
|
||||
case SpvCapabilityImageCubeArray:
|
||||
case spv::Capability::ImageCubeArray:
|
||||
return "ImageCubeArray";
|
||||
case SpvCapabilitySampleRateShading:
|
||||
case spv::Capability::SampleRateShading:
|
||||
return "SampleRateShading";
|
||||
case SpvCapabilityImageRect:
|
||||
case spv::Capability::ImageRect:
|
||||
return "ImageRect";
|
||||
case SpvCapabilitySampledRect:
|
||||
case spv::Capability::SampledRect:
|
||||
return "SampledRect";
|
||||
case SpvCapabilityGenericPointer:
|
||||
case spv::Capability::GenericPointer:
|
||||
return "GenericPointer";
|
||||
case SpvCapabilityInt8:
|
||||
case spv::Capability::Int8:
|
||||
return "Int8";
|
||||
case SpvCapabilityInputAttachment:
|
||||
case spv::Capability::InputAttachment:
|
||||
return "InputAttachment";
|
||||
case SpvCapabilitySparseResidency:
|
||||
case spv::Capability::SparseResidency:
|
||||
return "SparseResidency";
|
||||
case SpvCapabilityMinLod:
|
||||
case spv::Capability::MinLod:
|
||||
return "MinLod";
|
||||
case SpvCapabilitySampled1D:
|
||||
case spv::Capability::Sampled1D:
|
||||
return "Sampled1D";
|
||||
case SpvCapabilityImage1D:
|
||||
case spv::Capability::Image1D:
|
||||
return "Image1D";
|
||||
case SpvCapabilitySampledCubeArray:
|
||||
case spv::Capability::SampledCubeArray:
|
||||
return "SampledCubeArray";
|
||||
case SpvCapabilitySampledBuffer:
|
||||
case spv::Capability::SampledBuffer:
|
||||
return "SampledBuffer";
|
||||
case SpvCapabilityImageBuffer:
|
||||
case spv::Capability::ImageBuffer:
|
||||
return "ImageBuffer";
|
||||
case SpvCapabilityImageMSArray:
|
||||
case spv::Capability::ImageMSArray:
|
||||
return "ImageMSArray";
|
||||
case SpvCapabilityStorageImageExtendedFormats:
|
||||
case spv::Capability::StorageImageExtendedFormats:
|
||||
return "StorageImageExtendedFormats";
|
||||
case SpvCapabilityImageQuery:
|
||||
case spv::Capability::ImageQuery:
|
||||
return "ImageQuery";
|
||||
case SpvCapabilityDerivativeControl:
|
||||
case spv::Capability::DerivativeControl:
|
||||
return "DerivativeControl";
|
||||
case SpvCapabilityInterpolationFunction:
|
||||
case spv::Capability::InterpolationFunction:
|
||||
return "InterpolationFunction";
|
||||
case SpvCapabilityTransformFeedback:
|
||||
case spv::Capability::TransformFeedback:
|
||||
return "TransformFeedback";
|
||||
case SpvCapabilityGeometryStreams:
|
||||
case spv::Capability::GeometryStreams:
|
||||
return "GeometryStreams";
|
||||
case SpvCapabilityStorageImageReadWithoutFormat:
|
||||
case spv::Capability::StorageImageReadWithoutFormat:
|
||||
return "StorageImageReadWithoutFormat";
|
||||
case SpvCapabilityStorageImageWriteWithoutFormat:
|
||||
case spv::Capability::StorageImageWriteWithoutFormat:
|
||||
return "StorageImageWriteWithoutFormat";
|
||||
case SpvCapabilityMultiViewport:
|
||||
case spv::Capability::MultiViewport:
|
||||
return "MultiViewport";
|
||||
case SpvCapabilitySubgroupDispatch:
|
||||
case spv::Capability::SubgroupDispatch:
|
||||
return "SubgroupDispatch";
|
||||
case SpvCapabilityNamedBarrier:
|
||||
case spv::Capability::NamedBarrier:
|
||||
return "NamedBarrier";
|
||||
case SpvCapabilityPipeStorage:
|
||||
case spv::Capability::PipeStorage:
|
||||
return "PipeStorage";
|
||||
case SpvCapabilityGroupNonUniform:
|
||||
case spv::Capability::GroupNonUniform:
|
||||
return "GroupNonUniform";
|
||||
case SpvCapabilityGroupNonUniformVote:
|
||||
case spv::Capability::GroupNonUniformVote:
|
||||
return "GroupNonUniformVote";
|
||||
case SpvCapabilityGroupNonUniformArithmetic:
|
||||
case spv::Capability::GroupNonUniformArithmetic:
|
||||
return "GroupNonUniformArithmetic";
|
||||
case SpvCapabilityGroupNonUniformBallot:
|
||||
case spv::Capability::GroupNonUniformBallot:
|
||||
return "GroupNonUniformBallot";
|
||||
case SpvCapabilityGroupNonUniformShuffle:
|
||||
case spv::Capability::GroupNonUniformShuffle:
|
||||
return "GroupNonUniformShuffle";
|
||||
case SpvCapabilityGroupNonUniformShuffleRelative:
|
||||
case spv::Capability::GroupNonUniformShuffleRelative:
|
||||
return "GroupNonUniformShuffleRelative";
|
||||
case SpvCapabilityGroupNonUniformClustered:
|
||||
case spv::Capability::GroupNonUniformClustered:
|
||||
return "GroupNonUniformClustered";
|
||||
case SpvCapabilityGroupNonUniformQuad:
|
||||
case spv::Capability::GroupNonUniformQuad:
|
||||
return "GroupNonUniformQuad";
|
||||
case SpvCapabilityShaderLayer:
|
||||
case spv::Capability::ShaderLayer:
|
||||
return "ShaderLayer";
|
||||
case SpvCapabilityShaderViewportIndex:
|
||||
case spv::Capability::ShaderViewportIndex:
|
||||
return "ShaderViewportIndex";
|
||||
case SpvCapabilityUniformDecoration:
|
||||
case spv::Capability::UniformDecoration:
|
||||
return "UniformDecoration";
|
||||
case SpvCapabilityCoreBuiltinsARM:
|
||||
case spv::Capability::CoreBuiltinsARM:
|
||||
return "CoreBuiltinsARM";
|
||||
case SpvCapabilityFragmentShadingRateKHR:
|
||||
case spv::Capability::FragmentShadingRateKHR:
|
||||
return "FragmentShadingRateKHR";
|
||||
case SpvCapabilitySubgroupBallotKHR:
|
||||
case spv::Capability::SubgroupBallotKHR:
|
||||
return "SubgroupBallotKHR";
|
||||
case SpvCapabilityDrawParameters:
|
||||
case spv::Capability::DrawParameters:
|
||||
return "DrawParameters";
|
||||
case SpvCapabilityWorkgroupMemoryExplicitLayoutKHR:
|
||||
case spv::Capability::WorkgroupMemoryExplicitLayoutKHR:
|
||||
return "WorkgroupMemoryExplicitLayoutKHR";
|
||||
case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:
|
||||
case spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR:
|
||||
return "WorkgroupMemoryExplicitLayout8BitAccessKHR";
|
||||
case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR:
|
||||
case spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR:
|
||||
return "WorkgroupMemoryExplicitLayout16BitAccessKHR";
|
||||
case SpvCapabilitySubgroupVoteKHR:
|
||||
case spv::Capability::SubgroupVoteKHR:
|
||||
return "SubgroupVoteKHR";
|
||||
case SpvCapabilityStorageBuffer16BitAccess:
|
||||
case spv::Capability::StorageBuffer16BitAccess:
|
||||
return "StorageBuffer16BitAccess";
|
||||
case SpvCapabilityUniformAndStorageBuffer16BitAccess:
|
||||
case spv::Capability::UniformAndStorageBuffer16BitAccess:
|
||||
return "UniformAndStorageBuffer16BitAccess";
|
||||
case SpvCapabilityStoragePushConstant16:
|
||||
case spv::Capability::StoragePushConstant16:
|
||||
return "StoragePushConstant16";
|
||||
case SpvCapabilityStorageInputOutput16:
|
||||
case spv::Capability::StorageInputOutput16:
|
||||
return "StorageInputOutput16";
|
||||
case SpvCapabilityDeviceGroup:
|
||||
case spv::Capability::DeviceGroup:
|
||||
return "DeviceGroup";
|
||||
case SpvCapabilityMultiView:
|
||||
case spv::Capability::MultiView:
|
||||
return "MultiView";
|
||||
case SpvCapabilityVariablePointersStorageBuffer:
|
||||
case spv::Capability::VariablePointersStorageBuffer:
|
||||
return "VariablePointersStorageBuffer";
|
||||
case SpvCapabilityVariablePointers:
|
||||
case spv::Capability::VariablePointers:
|
||||
return "VariablePointers";
|
||||
case SpvCapabilityAtomicStorageOps:
|
||||
case spv::Capability::AtomicStorageOps:
|
||||
return "AtomicStorageOps";
|
||||
case SpvCapabilitySampleMaskPostDepthCoverage:
|
||||
case spv::Capability::SampleMaskPostDepthCoverage:
|
||||
return "SampleMaskPostDepthCoverage";
|
||||
case SpvCapabilityStorageBuffer8BitAccess:
|
||||
case spv::Capability::StorageBuffer8BitAccess:
|
||||
return "StorageBuffer8BitAccess";
|
||||
case SpvCapabilityUniformAndStorageBuffer8BitAccess:
|
||||
case spv::Capability::UniformAndStorageBuffer8BitAccess:
|
||||
return "UniformAndStorageBuffer8BitAccess";
|
||||
case SpvCapabilityStoragePushConstant8:
|
||||
case spv::Capability::StoragePushConstant8:
|
||||
return "StoragePushConstant8";
|
||||
case SpvCapabilityDenormPreserve:
|
||||
case spv::Capability::DenormPreserve:
|
||||
return "DenormPreserve";
|
||||
case SpvCapabilityDenormFlushToZero:
|
||||
case spv::Capability::DenormFlushToZero:
|
||||
return "DenormFlushToZero";
|
||||
case SpvCapabilitySignedZeroInfNanPreserve:
|
||||
case spv::Capability::SignedZeroInfNanPreserve:
|
||||
return "SignedZeroInfNanPreserve";
|
||||
case SpvCapabilityRoundingModeRTE:
|
||||
case spv::Capability::RoundingModeRTE:
|
||||
return "RoundingModeRTE";
|
||||
case SpvCapabilityRoundingModeRTZ:
|
||||
case spv::Capability::RoundingModeRTZ:
|
||||
return "RoundingModeRTZ";
|
||||
case SpvCapabilityRayQueryProvisionalKHR:
|
||||
case spv::Capability::RayQueryProvisionalKHR:
|
||||
return "RayQueryProvisionalKHR";
|
||||
case SpvCapabilityRayQueryKHR:
|
||||
case spv::Capability::RayQueryKHR:
|
||||
return "RayQueryKHR";
|
||||
case SpvCapabilityRayTraversalPrimitiveCullingKHR:
|
||||
case spv::Capability::RayTraversalPrimitiveCullingKHR:
|
||||
return "RayTraversalPrimitiveCullingKHR";
|
||||
case SpvCapabilityRayTracingKHR:
|
||||
case spv::Capability::RayTracingKHR:
|
||||
return "RayTracingKHR";
|
||||
case SpvCapabilityFloat16ImageAMD:
|
||||
case spv::Capability::Float16ImageAMD:
|
||||
return "Float16ImageAMD";
|
||||
case SpvCapabilityImageGatherBiasLodAMD:
|
||||
case spv::Capability::ImageGatherBiasLodAMD:
|
||||
return "ImageGatherBiasLodAMD";
|
||||
case SpvCapabilityFragmentMaskAMD:
|
||||
case spv::Capability::FragmentMaskAMD:
|
||||
return "FragmentMaskAMD";
|
||||
case SpvCapabilityStencilExportEXT:
|
||||
case spv::Capability::StencilExportEXT:
|
||||
return "StencilExportEXT";
|
||||
case SpvCapabilityImageReadWriteLodAMD:
|
||||
case spv::Capability::ImageReadWriteLodAMD:
|
||||
return "ImageReadWriteLodAMD";
|
||||
case SpvCapabilityInt64ImageEXT:
|
||||
case spv::Capability::Int64ImageEXT:
|
||||
return "Int64ImageEXT";
|
||||
case SpvCapabilityShaderClockKHR:
|
||||
case spv::Capability::ShaderClockKHR:
|
||||
return "ShaderClockKHR";
|
||||
case SpvCapabilitySampleMaskOverrideCoverageNV:
|
||||
case spv::Capability::SampleMaskOverrideCoverageNV:
|
||||
return "SampleMaskOverrideCoverageNV";
|
||||
case SpvCapabilityGeometryShaderPassthroughNV:
|
||||
case spv::Capability::GeometryShaderPassthroughNV:
|
||||
return "GeometryShaderPassthroughNV";
|
||||
case SpvCapabilityShaderViewportIndexLayerEXT:
|
||||
case spv::Capability::ShaderViewportIndexLayerEXT:
|
||||
return "ShaderViewportIndexLayerEXT";
|
||||
case SpvCapabilityShaderViewportMaskNV:
|
||||
case spv::Capability::ShaderViewportMaskNV:
|
||||
return "ShaderViewportMaskNV";
|
||||
case SpvCapabilityShaderStereoViewNV:
|
||||
case spv::Capability::ShaderStereoViewNV:
|
||||
return "ShaderStereoViewNV";
|
||||
case SpvCapabilityPerViewAttributesNV:
|
||||
case spv::Capability::PerViewAttributesNV:
|
||||
return "PerViewAttributesNV";
|
||||
case SpvCapabilityFragmentFullyCoveredEXT:
|
||||
case spv::Capability::FragmentFullyCoveredEXT:
|
||||
return "FragmentFullyCoveredEXT";
|
||||
case SpvCapabilityMeshShadingNV:
|
||||
case spv::Capability::MeshShadingNV:
|
||||
return "MeshShadingNV";
|
||||
case SpvCapabilityImageFootprintNV:
|
||||
case spv::Capability::ImageFootprintNV:
|
||||
return "ImageFootprintNV";
|
||||
case SpvCapabilityMeshShadingEXT:
|
||||
case spv::Capability::MeshShadingEXT:
|
||||
return "MeshShadingEXT";
|
||||
case SpvCapabilityFragmentBarycentricKHR:
|
||||
case spv::Capability::FragmentBarycentricKHR:
|
||||
return "FragmentBarycentricKHR";
|
||||
case SpvCapabilityComputeDerivativeGroupQuadsNV:
|
||||
case spv::Capability::ComputeDerivativeGroupQuadsNV:
|
||||
return "ComputeDerivativeGroupQuadsNV";
|
||||
case SpvCapabilityFragmentDensityEXT:
|
||||
case spv::Capability::FragmentDensityEXT:
|
||||
return "FragmentDensityEXT";
|
||||
case SpvCapabilityGroupNonUniformPartitionedNV:
|
||||
case spv::Capability::GroupNonUniformPartitionedNV:
|
||||
return "GroupNonUniformPartitionedNV";
|
||||
case SpvCapabilityShaderNonUniform:
|
||||
case spv::Capability::ShaderNonUniform:
|
||||
return "ShaderNonUniform";
|
||||
case SpvCapabilityRuntimeDescriptorArray:
|
||||
case spv::Capability::RuntimeDescriptorArray:
|
||||
return "RuntimeDescriptorArray";
|
||||
case SpvCapabilityInputAttachmentArrayDynamicIndexing:
|
||||
case spv::Capability::InputAttachmentArrayDynamicIndexing:
|
||||
return "InputAttachmentArrayDynamicIndexing";
|
||||
case SpvCapabilityUniformTexelBufferArrayDynamicIndexing:
|
||||
case spv::Capability::UniformTexelBufferArrayDynamicIndexing:
|
||||
return "UniformTexelBufferArrayDynamicIndexing";
|
||||
case SpvCapabilityStorageTexelBufferArrayDynamicIndexing:
|
||||
case spv::Capability::StorageTexelBufferArrayDynamicIndexing:
|
||||
return "StorageTexelBufferArrayDynamicIndexing";
|
||||
case SpvCapabilityUniformBufferArrayNonUniformIndexing:
|
||||
case spv::Capability::UniformBufferArrayNonUniformIndexing:
|
||||
return "UniformBufferArrayNonUniformIndexing";
|
||||
case SpvCapabilitySampledImageArrayNonUniformIndexing:
|
||||
case spv::Capability::SampledImageArrayNonUniformIndexing:
|
||||
return "SampledImageArrayNonUniformIndexing";
|
||||
case SpvCapabilityStorageBufferArrayNonUniformIndexing:
|
||||
case spv::Capability::StorageBufferArrayNonUniformIndexing:
|
||||
return "StorageBufferArrayNonUniformIndexing";
|
||||
case SpvCapabilityStorageImageArrayNonUniformIndexing:
|
||||
case spv::Capability::StorageImageArrayNonUniformIndexing:
|
||||
return "StorageImageArrayNonUniformIndexing";
|
||||
case SpvCapabilityInputAttachmentArrayNonUniformIndexing:
|
||||
case spv::Capability::InputAttachmentArrayNonUniformIndexing:
|
||||
return "InputAttachmentArrayNonUniformIndexing";
|
||||
case SpvCapabilityUniformTexelBufferArrayNonUniformIndexing:
|
||||
case spv::Capability::UniformTexelBufferArrayNonUniformIndexing:
|
||||
return "UniformTexelBufferArrayNonUniformIndexing";
|
||||
case SpvCapabilityStorageTexelBufferArrayNonUniformIndexing:
|
||||
case spv::Capability::StorageTexelBufferArrayNonUniformIndexing:
|
||||
return "StorageTexelBufferArrayNonUniformIndexing";
|
||||
case SpvCapabilityRayTracingNV:
|
||||
case spv::Capability::RayTracingNV:
|
||||
return "RayTracingNV";
|
||||
case SpvCapabilityRayTracingMotionBlurNV:
|
||||
case spv::Capability::RayTracingMotionBlurNV:
|
||||
return "RayTracingMotionBlurNV";
|
||||
case SpvCapabilityVulkanMemoryModel:
|
||||
case spv::Capability::VulkanMemoryModel:
|
||||
return "VulkanMemoryModel";
|
||||
case SpvCapabilityVulkanMemoryModelDeviceScope:
|
||||
case spv::Capability::VulkanMemoryModelDeviceScope:
|
||||
return "VulkanMemoryModelDeviceScope";
|
||||
case SpvCapabilityPhysicalStorageBufferAddresses:
|
||||
case spv::Capability::PhysicalStorageBufferAddresses:
|
||||
return "PhysicalStorageBufferAddresses";
|
||||
case SpvCapabilityComputeDerivativeGroupLinearNV:
|
||||
case spv::Capability::ComputeDerivativeGroupLinearNV:
|
||||
return "ComputeDerivativeGroupLinearNV";
|
||||
case SpvCapabilityRayTracingProvisionalKHR:
|
||||
case spv::Capability::RayTracingProvisionalKHR:
|
||||
return "RayTracingProvisionalKHR";
|
||||
case SpvCapabilityCooperativeMatrixNV:
|
||||
case spv::Capability::CooperativeMatrixNV:
|
||||
return "CooperativeMatrixNV";
|
||||
case SpvCapabilityFragmentShaderSampleInterlockEXT:
|
||||
case spv::Capability::FragmentShaderSampleInterlockEXT:
|
||||
return "FragmentShaderSampleInterlockEXT";
|
||||
case SpvCapabilityFragmentShaderShadingRateInterlockEXT:
|
||||
case spv::Capability::FragmentShaderShadingRateInterlockEXT:
|
||||
return "FragmentShaderShadingRateInterlockEXT";
|
||||
case SpvCapabilityShaderSMBuiltinsNV:
|
||||
case spv::Capability::ShaderSMBuiltinsNV:
|
||||
return "ShaderSMBuiltinsNV";
|
||||
case SpvCapabilityFragmentShaderPixelInterlockEXT:
|
||||
case spv::Capability::FragmentShaderPixelInterlockEXT:
|
||||
return "FragmentShaderPixelInterlockEXT";
|
||||
case SpvCapabilityDemoteToHelperInvocation:
|
||||
case spv::Capability::DemoteToHelperInvocation:
|
||||
return "DemoteToHelperInvocation";
|
||||
case SpvCapabilityRayTracingOpacityMicromapEXT:
|
||||
case spv::Capability::RayTracingOpacityMicromapEXT:
|
||||
return "RayTracingOpacityMicromapEXT";
|
||||
case SpvCapabilityBindlessTextureNV:
|
||||
case spv::Capability::ShaderInvocationReorderNV:
|
||||
return "ShaderInvocationReorderNV";
|
||||
case spv::Capability::BindlessTextureNV:
|
||||
return "BindlessTextureNV";
|
||||
case SpvCapabilitySubgroupShuffleINTEL:
|
||||
case spv::Capability::SubgroupShuffleINTEL:
|
||||
return "SubgroupShuffleINTEL";
|
||||
case SpvCapabilitySubgroupBufferBlockIOINTEL:
|
||||
case spv::Capability::SubgroupBufferBlockIOINTEL:
|
||||
return "SubgroupBufferBlockIOINTEL";
|
||||
case SpvCapabilitySubgroupImageBlockIOINTEL:
|
||||
case spv::Capability::SubgroupImageBlockIOINTEL:
|
||||
return "SubgroupImageBlockIOINTEL";
|
||||
case SpvCapabilitySubgroupImageMediaBlockIOINTEL:
|
||||
case spv::Capability::SubgroupImageMediaBlockIOINTEL:
|
||||
return "SubgroupImageMediaBlockIOINTEL";
|
||||
case SpvCapabilityRoundToInfinityINTEL:
|
||||
case spv::Capability::RoundToInfinityINTEL:
|
||||
return "RoundToInfinityINTEL";
|
||||
case SpvCapabilityFloatingPointModeINTEL:
|
||||
case spv::Capability::FloatingPointModeINTEL:
|
||||
return "FloatingPointModeINTEL";
|
||||
case SpvCapabilityIntegerFunctions2INTEL:
|
||||
case spv::Capability::IntegerFunctions2INTEL:
|
||||
return "IntegerFunctions2INTEL";
|
||||
case SpvCapabilityFunctionPointersINTEL:
|
||||
case spv::Capability::FunctionPointersINTEL:
|
||||
return "FunctionPointersINTEL";
|
||||
case SpvCapabilityIndirectReferencesINTEL:
|
||||
case spv::Capability::IndirectReferencesINTEL:
|
||||
return "IndirectReferencesINTEL";
|
||||
case SpvCapabilityAsmINTEL:
|
||||
case spv::Capability::AsmINTEL:
|
||||
return "AsmINTEL";
|
||||
case SpvCapabilityAtomicFloat32MinMaxEXT:
|
||||
case spv::Capability::AtomicFloat32MinMaxEXT:
|
||||
return "AtomicFloat32MinMaxEXT";
|
||||
case SpvCapabilityAtomicFloat64MinMaxEXT:
|
||||
case spv::Capability::AtomicFloat64MinMaxEXT:
|
||||
return "AtomicFloat64MinMaxEXT";
|
||||
case SpvCapabilityAtomicFloat16MinMaxEXT:
|
||||
case spv::Capability::AtomicFloat16MinMaxEXT:
|
||||
return "AtomicFloat16MinMaxEXT";
|
||||
case SpvCapabilityVectorComputeINTEL:
|
||||
case spv::Capability::VectorComputeINTEL:
|
||||
return "VectorComputeINTEL";
|
||||
case SpvCapabilityVectorAnyINTEL:
|
||||
case spv::Capability::VectorAnyINTEL:
|
||||
return "VectorAnyINTEL";
|
||||
case SpvCapabilityExpectAssumeKHR:
|
||||
case spv::Capability::ExpectAssumeKHR:
|
||||
return "ExpectAssumeKHR";
|
||||
case SpvCapabilitySubgroupAvcMotionEstimationINTEL:
|
||||
case spv::Capability::SubgroupAvcMotionEstimationINTEL:
|
||||
return "SubgroupAvcMotionEstimationINTEL";
|
||||
case SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL:
|
||||
case spv::Capability::SubgroupAvcMotionEstimationIntraINTEL:
|
||||
return "SubgroupAvcMotionEstimationIntraINTEL";
|
||||
case SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL:
|
||||
case spv::Capability::SubgroupAvcMotionEstimationChromaINTEL:
|
||||
return "SubgroupAvcMotionEstimationChromaINTEL";
|
||||
case SpvCapabilityVariableLengthArrayINTEL:
|
||||
case spv::Capability::VariableLengthArrayINTEL:
|
||||
return "VariableLengthArrayINTEL";
|
||||
case SpvCapabilityFunctionFloatControlINTEL:
|
||||
case spv::Capability::FunctionFloatControlINTEL:
|
||||
return "FunctionFloatControlINTEL";
|
||||
case SpvCapabilityFPGAMemoryAttributesINTEL:
|
||||
case spv::Capability::FPGAMemoryAttributesINTEL:
|
||||
return "FPGAMemoryAttributesINTEL";
|
||||
case SpvCapabilityFPFastMathModeINTEL:
|
||||
case spv::Capability::FPFastMathModeINTEL:
|
||||
return "FPFastMathModeINTEL";
|
||||
case SpvCapabilityArbitraryPrecisionIntegersINTEL:
|
||||
case spv::Capability::ArbitraryPrecisionIntegersINTEL:
|
||||
return "ArbitraryPrecisionIntegersINTEL";
|
||||
case SpvCapabilityArbitraryPrecisionFloatingPointINTEL:
|
||||
case spv::Capability::ArbitraryPrecisionFloatingPointINTEL:
|
||||
return "ArbitraryPrecisionFloatingPointINTEL";
|
||||
case SpvCapabilityUnstructuredLoopControlsINTEL:
|
||||
case spv::Capability::UnstructuredLoopControlsINTEL:
|
||||
return "UnstructuredLoopControlsINTEL";
|
||||
case SpvCapabilityFPGALoopControlsINTEL:
|
||||
case spv::Capability::FPGALoopControlsINTEL:
|
||||
return "FPGALoopControlsINTEL";
|
||||
case SpvCapabilityKernelAttributesINTEL:
|
||||
case spv::Capability::KernelAttributesINTEL:
|
||||
return "KernelAttributesINTEL";
|
||||
case SpvCapabilityFPGAKernelAttributesINTEL:
|
||||
case spv::Capability::FPGAKernelAttributesINTEL:
|
||||
return "FPGAKernelAttributesINTEL";
|
||||
case SpvCapabilityFPGAMemoryAccessesINTEL:
|
||||
case spv::Capability::FPGAMemoryAccessesINTEL:
|
||||
return "FPGAMemoryAccessesINTEL";
|
||||
case SpvCapabilityFPGAClusterAttributesINTEL:
|
||||
case spv::Capability::FPGAClusterAttributesINTEL:
|
||||
return "FPGAClusterAttributesINTEL";
|
||||
case SpvCapabilityLoopFuseINTEL:
|
||||
case spv::Capability::LoopFuseINTEL:
|
||||
return "LoopFuseINTEL";
|
||||
case SpvCapabilityMemoryAccessAliasingINTEL:
|
||||
case spv::Capability::FPGADSPControlINTEL:
|
||||
return "FPGADSPControlINTEL";
|
||||
case spv::Capability::MemoryAccessAliasingINTEL:
|
||||
return "MemoryAccessAliasingINTEL";
|
||||
case SpvCapabilityFPGABufferLocationINTEL:
|
||||
case spv::Capability::FPGAInvocationPipeliningAttributesINTEL:
|
||||
return "FPGAInvocationPipeliningAttributesINTEL";
|
||||
case spv::Capability::FPGABufferLocationINTEL:
|
||||
return "FPGABufferLocationINTEL";
|
||||
case SpvCapabilityArbitraryPrecisionFixedPointINTEL:
|
||||
case spv::Capability::ArbitraryPrecisionFixedPointINTEL:
|
||||
return "ArbitraryPrecisionFixedPointINTEL";
|
||||
case SpvCapabilityUSMStorageClassesINTEL:
|
||||
case spv::Capability::USMStorageClassesINTEL:
|
||||
return "USMStorageClassesINTEL";
|
||||
case SpvCapabilityIOPipesINTEL:
|
||||
case spv::Capability::RuntimeAlignedAttributeINTEL:
|
||||
return "RuntimeAlignedAttributeINTEL";
|
||||
case spv::Capability::IOPipesINTEL:
|
||||
return "IOPipesINTEL";
|
||||
case SpvCapabilityBlockingPipesINTEL:
|
||||
case spv::Capability::BlockingPipesINTEL:
|
||||
return "BlockingPipesINTEL";
|
||||
case SpvCapabilityFPGARegINTEL:
|
||||
case spv::Capability::FPGARegINTEL:
|
||||
return "FPGARegINTEL";
|
||||
case SpvCapabilityDotProductInputAll:
|
||||
case spv::Capability::DotProductInputAll:
|
||||
return "DotProductInputAll";
|
||||
case SpvCapabilityDotProductInput4x8Bit:
|
||||
case spv::Capability::DotProductInput4x8Bit:
|
||||
return "DotProductInput4x8Bit";
|
||||
case SpvCapabilityDotProductInput4x8BitPacked:
|
||||
case spv::Capability::DotProductInput4x8BitPacked:
|
||||
return "DotProductInput4x8BitPacked";
|
||||
case SpvCapabilityDotProduct:
|
||||
case spv::Capability::DotProduct:
|
||||
return "DotProduct";
|
||||
case SpvCapabilityRayCullMaskKHR:
|
||||
case spv::Capability::RayCullMaskKHR:
|
||||
return "RayCullMaskKHR";
|
||||
case SpvCapabilityBitInstructions:
|
||||
case spv::Capability::BitInstructions:
|
||||
return "BitInstructions";
|
||||
case SpvCapabilityGroupNonUniformRotateKHR:
|
||||
case spv::Capability::GroupNonUniformRotateKHR:
|
||||
return "GroupNonUniformRotateKHR";
|
||||
case SpvCapabilityAtomicFloat32AddEXT:
|
||||
case spv::Capability::AtomicFloat32AddEXT:
|
||||
return "AtomicFloat32AddEXT";
|
||||
case SpvCapabilityAtomicFloat64AddEXT:
|
||||
case spv::Capability::AtomicFloat64AddEXT:
|
||||
return "AtomicFloat64AddEXT";
|
||||
case SpvCapabilityLongConstantCompositeINTEL:
|
||||
case spv::Capability::LongConstantCompositeINTEL:
|
||||
return "LongConstantCompositeINTEL";
|
||||
case SpvCapabilityOptNoneINTEL:
|
||||
case spv::Capability::OptNoneINTEL:
|
||||
return "OptNoneINTEL";
|
||||
case SpvCapabilityAtomicFloat16AddEXT:
|
||||
case spv::Capability::AtomicFloat16AddEXT:
|
||||
return "AtomicFloat16AddEXT";
|
||||
case SpvCapabilityDebugInfoModuleINTEL:
|
||||
case spv::Capability::DebugInfoModuleINTEL:
|
||||
return "DebugInfoModuleINTEL";
|
||||
case SpvCapabilitySplitBarrierINTEL:
|
||||
case spv::Capability::SplitBarrierINTEL:
|
||||
return "SplitBarrierINTEL";
|
||||
case SpvCapabilityGroupUniformArithmeticKHR:
|
||||
case spv::Capability::GroupUniformArithmeticKHR:
|
||||
return "GroupUniformArithmeticKHR";
|
||||
case SpvCapabilityMax:
|
||||
assert(0 && "Attempting to convert SpvCapabilityMax to string");
|
||||
case spv::Capability::Max:
|
||||
assert(0 && "Attempting to convert spv::Capability::Max to string");
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ kSPV_INTEL_float_controls2,
|
||||
kSPV_INTEL_fp_fast_math_mode,
|
||||
kSPV_INTEL_fpga_buffer_location,
|
||||
kSPV_INTEL_fpga_cluster_attributes,
|
||||
kSPV_INTEL_fpga_dsp_control,
|
||||
kSPV_INTEL_fpga_invocation_pipelining_attributes,
|
||||
kSPV_INTEL_fpga_loop_controls,
|
||||
kSPV_INTEL_fpga_memory_accesses,
|
||||
kSPV_INTEL_fpga_memory_attributes,
|
||||
@@ -50,6 +52,7 @@ kSPV_INTEL_loop_fuse,
|
||||
kSPV_INTEL_media_block_io,
|
||||
kSPV_INTEL_memory_access_aliasing,
|
||||
kSPV_INTEL_optnone,
|
||||
kSPV_INTEL_runtime_aligned,
|
||||
kSPV_INTEL_shader_integer_functions2,
|
||||
kSPV_INTEL_split_barrier,
|
||||
kSPV_INTEL_subgroups,
|
||||
@@ -99,6 +102,7 @@ kSPV_NV_ray_tracing,
|
||||
kSPV_NV_ray_tracing_motion_blur,
|
||||
kSPV_NV_sample_mask_override_coverage,
|
||||
kSPV_NV_shader_image_footprint,
|
||||
kSPV_NV_shader_invocation_reorder,
|
||||
kSPV_NV_shader_sm_builtins,
|
||||
kSPV_NV_shader_subgroup_partitioned,
|
||||
kSPV_NV_shading_rate,
|
||||
|
||||
@@ -33,4 +33,5 @@
|
||||
{32, "TornadoVM", "SPIRV Beehive Toolkit", "TornadoVM SPIRV Beehive Toolkit"},
|
||||
{33, "DragonJoker", "ShaderWriter", "DragonJoker ShaderWriter"},
|
||||
{34, "Rayan Hatout", "SPIRVSmith", "Rayan Hatout SPIRVSmith"},
|
||||
{35, "Saarland University", "Shady", "Saarland University Shady"},
|
||||
{35, "Saarland University", "Shady", "Saarland University Shady"},
|
||||
{36, "Taichi Graphics", "Taichi", "Taichi Graphics Taichi"},
|
||||
@@ -1,5 +1,5 @@
|
||||
static const SpvCapability pygen_variable_caps_Float64[] = {SpvCapabilityFloat64};
|
||||
static const SpvCapability pygen_variable_caps_InterpolationFunction[] = {SpvCapabilityInterpolationFunction};
|
||||
static const spv::Capability pygen_variable_caps_Float64[] = {spv::Capability::Float64};
|
||||
static const spv::Capability pygen_variable_caps_InterpolationFunction[] = {spv::Capability::InterpolationFunction};
|
||||
|
||||
static const spv_ext_inst_desc_t glsl_entries[] = {
|
||||
{"Round", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
static const spv_ext_inst_desc_t nonsemantic_clspvreflection_entries[] = {
|
||||
{"Kernel", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Kernel", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ArgumentInfo", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ArgumentStorageBuffer", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ArgumentUniform", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
@@ -35,5 +35,10 @@ static const spv_ext_inst_desc_t nonsemantic_clspvreflection_entries[] = {
|
||||
{"ImageArgumentInfoChannelOrderUniform", 32, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ImageArgumentInfoChannelDataTypeUniform", 33, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ArgumentStorageTexelBuffer", 34, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ArgumentUniformTexelBuffer", 35, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
{"ArgumentUniformTexelBuffer", 35, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ConstantDataPointerPushConstant", 36, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ProgramScopeVariablePointerPushConstant", 37, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PrintfInfo", 38, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PrintfBufferStorageBuffer", 39, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PrintfBufferPointerPushConstant", 40, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
@@ -1,129 +1,133 @@
|
||||
static const SpvCapability pygen_variable_caps_Addresses[] = {SpvCapabilityAddresses};
|
||||
static const SpvCapability pygen_variable_caps_ArbitraryPrecisionFixedPointINTEL[] = {SpvCapabilityArbitraryPrecisionFixedPointINTEL};
|
||||
static const SpvCapability pygen_variable_caps_AsmINTEL[] = {SpvCapabilityAsmINTEL};
|
||||
static const SpvCapability pygen_variable_caps_AtomicStorage[] = {SpvCapabilityAtomicStorage};
|
||||
static const SpvCapability pygen_variable_caps_BindlessTextureNV[] = {SpvCapabilityBindlessTextureNV};
|
||||
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_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};
|
||||
static const SpvCapability pygen_variable_caps_FPGAKernelAttributesINTEL[] = {SpvCapabilityFPGAKernelAttributesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_FPGALoopControlsINTEL[] = {SpvCapabilityFPGALoopControlsINTEL};
|
||||
static const SpvCapability pygen_variable_caps_FPGAMemoryAccessesINTEL[] = {SpvCapabilityFPGAMemoryAccessesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_FPGAMemoryAttributesINTEL[] = {SpvCapabilityFPGAMemoryAttributesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR[] = {SpvCapabilityFragmentBarycentricNV, SpvCapabilityFragmentBarycentricKHR};
|
||||
static const SpvCapability pygen_variable_caps_FragmentDensityEXTShadingRateNV[] = {SpvCapabilityFragmentDensityEXT, SpvCapabilityShadingRateNV};
|
||||
static const SpvCapability pygen_variable_caps_FragmentFullyCoveredEXT[] = {SpvCapabilityFragmentFullyCoveredEXT};
|
||||
static const SpvCapability pygen_variable_caps_FragmentShaderPixelInterlockEXT[] = {SpvCapabilityFragmentShaderPixelInterlockEXT};
|
||||
static const SpvCapability pygen_variable_caps_FragmentShaderSampleInterlockEXT[] = {SpvCapabilityFragmentShaderSampleInterlockEXT};
|
||||
static const SpvCapability pygen_variable_caps_FragmentShaderShadingRateInterlockEXT[] = {SpvCapabilityFragmentShaderShadingRateInterlockEXT};
|
||||
static const SpvCapability pygen_variable_caps_FragmentShadingRateKHR[] = {SpvCapabilityFragmentShadingRateKHR};
|
||||
static const SpvCapability pygen_variable_caps_FunctionFloatControlINTEL[] = {SpvCapabilityFunctionFloatControlINTEL};
|
||||
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_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_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};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformClustered[] = {SpvCapabilityGroupNonUniformClustered};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformPartitionedNV};
|
||||
static const SpvCapability pygen_variable_caps_IOPipesINTEL[] = {SpvCapabilityIOPipesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_ImageBasic[] = {SpvCapabilityImageBasic};
|
||||
static const SpvCapability pygen_variable_caps_ImageBuffer[] = {SpvCapabilityImageBuffer};
|
||||
static const SpvCapability pygen_variable_caps_ImageBufferShaderNonUniform[] = {SpvCapabilityImageBuffer, SpvCapabilityShaderNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_ImageGatherExtended[] = {SpvCapabilityImageGatherExtended};
|
||||
static const SpvCapability pygen_variable_caps_IndirectReferencesINTEL[] = {SpvCapabilityIndirectReferencesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_InputAttachment[] = {SpvCapabilityInputAttachment};
|
||||
static const SpvCapability pygen_variable_caps_InputAttachmentShaderNonUniform[] = {SpvCapabilityInputAttachment, SpvCapabilityShaderNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_Int64[] = {SpvCapabilityInt64};
|
||||
static const SpvCapability pygen_variable_caps_Int64ImageEXT[] = {SpvCapabilityInt64ImageEXT};
|
||||
static const SpvCapability pygen_variable_caps_Int8[] = {SpvCapabilityInt8};
|
||||
static const SpvCapability pygen_variable_caps_Kernel[] = {SpvCapabilityKernel};
|
||||
static const SpvCapability pygen_variable_caps_KernelGroupNonUniform[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform, SpvCapabilitySubgroupBallotKHR};
|
||||
static const SpvCapability pygen_variable_caps_KernelGroupNonUniformArithmeticGroupNonUniformBallot[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformBallot};
|
||||
static const SpvCapability pygen_variable_caps_KernelAttributesINTEL[] = {SpvCapabilityKernelAttributesINTEL};
|
||||
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_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};
|
||||
static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes};
|
||||
static const SpvCapability pygen_variable_caps_RayCullMaskKHR[] = {SpvCapabilityRayCullMaskKHR};
|
||||
static const SpvCapability pygen_variable_caps_RayQueryKHR[] = {SpvCapabilityRayQueryKHR};
|
||||
static const SpvCapability pygen_variable_caps_RayQueryKHRRayTracingKHR[] = {SpvCapabilityRayQueryKHR, SpvCapabilityRayTracingKHR};
|
||||
static const SpvCapability pygen_variable_caps_RayTracingKHR[] = {SpvCapabilityRayTracingKHR};
|
||||
static const SpvCapability pygen_variable_caps_RayTracingMotionBlurNV[] = {SpvCapabilityRayTracingMotionBlurNV};
|
||||
static const SpvCapability pygen_variable_caps_RayTracingNV[] = {SpvCapabilityRayTracingNV};
|
||||
static const SpvCapability pygen_variable_caps_RayTracingNVRayTracingKHR[] = {SpvCapabilityRayTracingNV, SpvCapabilityRayTracingKHR};
|
||||
static const SpvCapability pygen_variable_caps_RayTracingOpacityMicromapEXT[] = {SpvCapabilityRayTracingOpacityMicromapEXT};
|
||||
static const SpvCapability pygen_variable_caps_RayTraversalPrimitiveCullingKHR[] = {SpvCapabilityRayTraversalPrimitiveCullingKHR};
|
||||
static const SpvCapability pygen_variable_caps_RoundToInfinityINTEL[] = {SpvCapabilityRoundToInfinityINTEL};
|
||||
static const SpvCapability pygen_variable_caps_RoundingModeRTE[] = {SpvCapabilityRoundingModeRTE};
|
||||
static const SpvCapability pygen_variable_caps_RoundingModeRTZ[] = {SpvCapabilityRoundingModeRTZ};
|
||||
static const SpvCapability pygen_variable_caps_SampleMaskOverrideCoverageNV[] = {SpvCapabilitySampleMaskOverrideCoverageNV};
|
||||
static const SpvCapability pygen_variable_caps_SampleMaskPostDepthCoverage[] = {SpvCapabilitySampleMaskPostDepthCoverage};
|
||||
static const SpvCapability pygen_variable_caps_SampleRateShading[] = {SpvCapabilitySampleRateShading};
|
||||
static const SpvCapability pygen_variable_caps_Sampled1D[] = {SpvCapabilitySampled1D};
|
||||
static const SpvCapability pygen_variable_caps_Sampled1DImage1D[] = {SpvCapabilitySampled1D, SpvCapabilityImage1D};
|
||||
static const SpvCapability pygen_variable_caps_SampledBuffer[] = {SpvCapabilitySampledBuffer};
|
||||
static const SpvCapability pygen_variable_caps_SampledBufferImageBuffer[] = {SpvCapabilitySampledBuffer, SpvCapabilityImageBuffer};
|
||||
static const SpvCapability pygen_variable_caps_SampledBufferShaderNonUniform[] = {SpvCapabilitySampledBuffer, SpvCapabilityShaderNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_SampledCubeArray[] = {SpvCapabilitySampledCubeArray};
|
||||
static const SpvCapability pygen_variable_caps_SampledRect[] = {SpvCapabilitySampledRect};
|
||||
static const SpvCapability pygen_variable_caps_SampledRectImageRect[] = {SpvCapabilitySampledRect, SpvCapabilityImageRect};
|
||||
static const SpvCapability pygen_variable_caps_Shader[] = {SpvCapabilityShader};
|
||||
static const SpvCapability pygen_variable_caps_ShaderImageCubeArray[] = {SpvCapabilityShader, SpvCapabilityImageCubeArray};
|
||||
static const SpvCapability pygen_variable_caps_ShaderKernel[] = {SpvCapabilityShader, SpvCapabilityKernel};
|
||||
static const SpvCapability pygen_variable_caps_ShaderKernelImageMSArray[] = {SpvCapabilityShader, SpvCapabilityKernel, SpvCapabilityImageMSArray};
|
||||
static const SpvCapability pygen_variable_caps_ShaderUniformDecoration[] = {SpvCapabilityShader, SpvCapabilityUniformDecoration};
|
||||
static const SpvCapability pygen_variable_caps_ShaderVectorComputeINTEL[] = {SpvCapabilityShader, SpvCapabilityVectorComputeINTEL};
|
||||
static const SpvCapability pygen_variable_caps_ShaderNonUniform[] = {SpvCapabilityShaderNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_ShaderSMBuiltinsNV[] = {SpvCapabilityShaderSMBuiltinsNV};
|
||||
static const SpvCapability pygen_variable_caps_ShaderStereoViewNV[] = {SpvCapabilityShaderStereoViewNV};
|
||||
static const SpvCapability pygen_variable_caps_ShaderViewportIndexLayerNV[] = {SpvCapabilityShaderViewportIndexLayerNV};
|
||||
static const SpvCapability pygen_variable_caps_ShaderViewportMaskNV[] = {SpvCapabilityShaderViewportMaskNV};
|
||||
static const SpvCapability pygen_variable_caps_ShaderViewportMaskNVMeshShadingNV[] = {SpvCapabilityShaderViewportMaskNV, SpvCapabilityMeshShadingNV};
|
||||
static const SpvCapability pygen_variable_caps_ShadingRateNVFragmentDensityEXT[] = {SpvCapabilityShadingRateNV, SpvCapabilityFragmentDensityEXT};
|
||||
static const SpvCapability pygen_variable_caps_SignedZeroInfNanPreserve[] = {SpvCapabilitySignedZeroInfNanPreserve};
|
||||
static const SpvCapability pygen_variable_caps_StencilExportEXT[] = {SpvCapabilityStencilExportEXT};
|
||||
static const SpvCapability pygen_variable_caps_StorageBuffer16BitAccessStorageUniformBufferBlock16[] = {SpvCapabilityStorageBuffer16BitAccess, SpvCapabilityStorageUniformBufferBlock16};
|
||||
static const SpvCapability pygen_variable_caps_StorageBuffer8BitAccess[] = {SpvCapabilityStorageBuffer8BitAccess};
|
||||
static const SpvCapability pygen_variable_caps_StorageImageExtendedFormats[] = {SpvCapabilityStorageImageExtendedFormats};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot[] = {SpvCapabilitySubgroupBallotKHR, SpvCapabilityGroupNonUniformBallot};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupDispatch[] = {SpvCapabilitySubgroupDispatch};
|
||||
static const SpvCapability pygen_variable_caps_Tessellation[] = {SpvCapabilityTessellation};
|
||||
static const SpvCapability pygen_variable_caps_TransformFeedback[] = {SpvCapabilityTransformFeedback};
|
||||
static const SpvCapability pygen_variable_caps_USMStorageClassesINTEL[] = {SpvCapabilityUSMStorageClassesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_VariablePointersStorageBuffer[] = {SpvCapabilityVariablePointersStorageBuffer};
|
||||
static const SpvCapability pygen_variable_caps_VectorAnyINTEL[] = {SpvCapabilityVectorAnyINTEL};
|
||||
static const SpvCapability pygen_variable_caps_VectorComputeINTEL[] = {SpvCapabilityVectorComputeINTEL};
|
||||
static const SpvCapability pygen_variable_caps_VulkanMemoryModel[] = {SpvCapabilityVulkanMemoryModel};
|
||||
static const SpvCapability pygen_variable_caps_WorkgroupMemoryExplicitLayoutKHR[] = {SpvCapabilityWorkgroupMemoryExplicitLayoutKHR};
|
||||
static const spv::Capability pygen_variable_caps_Addresses[] = {spv::Capability::Addresses};
|
||||
static const spv::Capability pygen_variable_caps_ArbitraryPrecisionFixedPointINTEL[] = {spv::Capability::ArbitraryPrecisionFixedPointINTEL};
|
||||
static const spv::Capability pygen_variable_caps_AsmINTEL[] = {spv::Capability::AsmINTEL};
|
||||
static const spv::Capability pygen_variable_caps_AtomicStorage[] = {spv::Capability::AtomicStorage};
|
||||
static const spv::Capability pygen_variable_caps_BindlessTextureNV[] = {spv::Capability::BindlessTextureNV};
|
||||
static const spv::Capability pygen_variable_caps_ClipDistance[] = {spv::Capability::ClipDistance};
|
||||
static const spv::Capability pygen_variable_caps_ComputeDerivativeGroupLinearNV[] = {spv::Capability::ComputeDerivativeGroupLinearNV};
|
||||
static const spv::Capability pygen_variable_caps_ComputeDerivativeGroupQuadsNV[] = {spv::Capability::ComputeDerivativeGroupQuadsNV};
|
||||
static const spv::Capability pygen_variable_caps_CoreBuiltinsARM[] = {spv::Capability::CoreBuiltinsARM};
|
||||
static const spv::Capability pygen_variable_caps_CullDistance[] = {spv::Capability::CullDistance};
|
||||
static const spv::Capability pygen_variable_caps_DenormFlushToZero[] = {spv::Capability::DenormFlushToZero};
|
||||
static const spv::Capability pygen_variable_caps_DenormPreserve[] = {spv::Capability::DenormPreserve};
|
||||
static const spv::Capability pygen_variable_caps_DeviceEnqueue[] = {spv::Capability::DeviceEnqueue};
|
||||
static const spv::Capability pygen_variable_caps_DeviceGroup[] = {spv::Capability::DeviceGroup};
|
||||
static const spv::Capability pygen_variable_caps_DrawParameters[] = {spv::Capability::DrawParameters};
|
||||
static const spv::Capability pygen_variable_caps_DrawParametersMeshShadingNVMeshShadingEXT[] = {spv::Capability::DrawParameters, spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_FPFastMathModeINTEL[] = {spv::Capability::FPFastMathModeINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGABufferLocationINTEL[] = {spv::Capability::FPGABufferLocationINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGAClusterAttributesINTEL[] = {spv::Capability::FPGAClusterAttributesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGADSPControlINTEL[] = {spv::Capability::FPGADSPControlINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGAInvocationPipeliningAttributesINTEL[] = {spv::Capability::FPGAInvocationPipeliningAttributesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGAKernelAttributesINTEL[] = {spv::Capability::FPGAKernelAttributesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGALoopControlsINTEL[] = {spv::Capability::FPGALoopControlsINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGAMemoryAccessesINTEL[] = {spv::Capability::FPGAMemoryAccessesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FPGAMemoryAttributesINTEL[] = {spv::Capability::FPGAMemoryAttributesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR[] = {spv::Capability::FragmentBarycentricNV, spv::Capability::FragmentBarycentricKHR};
|
||||
static const spv::Capability pygen_variable_caps_FragmentDensityEXTShadingRateNV[] = {spv::Capability::FragmentDensityEXT, spv::Capability::ShadingRateNV};
|
||||
static const spv::Capability pygen_variable_caps_FragmentFullyCoveredEXT[] = {spv::Capability::FragmentFullyCoveredEXT};
|
||||
static const spv::Capability pygen_variable_caps_FragmentShaderPixelInterlockEXT[] = {spv::Capability::FragmentShaderPixelInterlockEXT};
|
||||
static const spv::Capability pygen_variable_caps_FragmentShaderSampleInterlockEXT[] = {spv::Capability::FragmentShaderSampleInterlockEXT};
|
||||
static const spv::Capability pygen_variable_caps_FragmentShaderShadingRateInterlockEXT[] = {spv::Capability::FragmentShaderShadingRateInterlockEXT};
|
||||
static const spv::Capability pygen_variable_caps_FragmentShadingRateKHR[] = {spv::Capability::FragmentShadingRateKHR};
|
||||
static const spv::Capability pygen_variable_caps_FunctionFloatControlINTEL[] = {spv::Capability::FunctionFloatControlINTEL};
|
||||
static const spv::Capability pygen_variable_caps_FunctionPointersINTEL[] = {spv::Capability::FunctionPointersINTEL};
|
||||
static const spv::Capability pygen_variable_caps_GenericPointer[] = {spv::Capability::GenericPointer};
|
||||
static const spv::Capability pygen_variable_caps_Geometry[] = {spv::Capability::Geometry};
|
||||
static const spv::Capability pygen_variable_caps_GeometryMeshShadingNVMeshShadingEXT[] = {spv::Capability::Geometry, spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_GeometryShaderLayerShaderViewportIndexLayerEXTMeshShadingNVMeshShadingEXT[] = {spv::Capability::Geometry, spv::Capability::ShaderLayer, spv::Capability::ShaderViewportIndexLayerEXT, spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_GeometryTessellation[] = {spv::Capability::Geometry, spv::Capability::Tessellation};
|
||||
static const spv::Capability pygen_variable_caps_GeometryTessellationMeshShadingNVMeshShadingEXT[] = {spv::Capability::Geometry, spv::Capability::Tessellation, spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_GeometryTessellationRayTracingNVRayTracingKHRMeshShadingNVMeshShadingEXT[] = {spv::Capability::Geometry, spv::Capability::Tessellation, spv::Capability::RayTracingNV, spv::Capability::RayTracingKHR, spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_GeometryShaderPassthroughNV[] = {spv::Capability::GeometryShaderPassthroughNV};
|
||||
static const spv::Capability pygen_variable_caps_GeometryStreams[] = {spv::Capability::GeometryStreams};
|
||||
static const spv::Capability pygen_variable_caps_GroupNonUniform[] = {spv::Capability::GroupNonUniform};
|
||||
static const spv::Capability pygen_variable_caps_GroupNonUniformClustered[] = {spv::Capability::GroupNonUniformClustered};
|
||||
static const spv::Capability pygen_variable_caps_GroupNonUniformPartitionedNV[] = {spv::Capability::GroupNonUniformPartitionedNV};
|
||||
static const spv::Capability pygen_variable_caps_IOPipesINTEL[] = {spv::Capability::IOPipesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_ImageBasic[] = {spv::Capability::ImageBasic};
|
||||
static const spv::Capability pygen_variable_caps_ImageBuffer[] = {spv::Capability::ImageBuffer};
|
||||
static const spv::Capability pygen_variable_caps_ImageBufferShaderNonUniform[] = {spv::Capability::ImageBuffer, spv::Capability::ShaderNonUniform};
|
||||
static const spv::Capability pygen_variable_caps_ImageGatherExtended[] = {spv::Capability::ImageGatherExtended};
|
||||
static const spv::Capability pygen_variable_caps_IndirectReferencesINTEL[] = {spv::Capability::IndirectReferencesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_InputAttachment[] = {spv::Capability::InputAttachment};
|
||||
static const spv::Capability pygen_variable_caps_InputAttachmentShaderNonUniform[] = {spv::Capability::InputAttachment, spv::Capability::ShaderNonUniform};
|
||||
static const spv::Capability pygen_variable_caps_Int64[] = {spv::Capability::Int64};
|
||||
static const spv::Capability pygen_variable_caps_Int64ImageEXT[] = {spv::Capability::Int64ImageEXT};
|
||||
static const spv::Capability pygen_variable_caps_Int8[] = {spv::Capability::Int8};
|
||||
static const spv::Capability pygen_variable_caps_Kernel[] = {spv::Capability::Kernel};
|
||||
static const spv::Capability pygen_variable_caps_KernelGroupNonUniform[] = {spv::Capability::Kernel, spv::Capability::GroupNonUniform};
|
||||
static const spv::Capability pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR[] = {spv::Capability::Kernel, spv::Capability::GroupNonUniform, spv::Capability::SubgroupBallotKHR};
|
||||
static const spv::Capability pygen_variable_caps_KernelGroupNonUniformArithmeticGroupNonUniformBallot[] = {spv::Capability::Kernel, spv::Capability::GroupNonUniformArithmetic, spv::Capability::GroupNonUniformBallot};
|
||||
static const spv::Capability pygen_variable_caps_KernelAttributesINTEL[] = {spv::Capability::KernelAttributesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_Linkage[] = {spv::Capability::Linkage};
|
||||
static const spv::Capability pygen_variable_caps_LoopFuseINTEL[] = {spv::Capability::LoopFuseINTEL};
|
||||
static const spv::Capability pygen_variable_caps_Matrix[] = {spv::Capability::Matrix};
|
||||
static const spv::Capability pygen_variable_caps_MemoryAccessAliasingINTEL[] = {spv::Capability::MemoryAccessAliasingINTEL};
|
||||
static const spv::Capability pygen_variable_caps_MeshShadingEXT[] = {spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_MeshShadingNV[] = {spv::Capability::MeshShadingNV};
|
||||
static const spv::Capability pygen_variable_caps_MeshShadingNVMeshShadingEXT[] = {spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_MinLod[] = {spv::Capability::MinLod};
|
||||
static const spv::Capability pygen_variable_caps_MultiView[] = {spv::Capability::MultiView};
|
||||
static const spv::Capability pygen_variable_caps_MultiViewport[] = {spv::Capability::MultiViewport};
|
||||
static const spv::Capability pygen_variable_caps_MultiViewportShaderViewportIndexShaderViewportIndexLayerEXTMeshShadingNVMeshShadingEXT[] = {spv::Capability::MultiViewport, spv::Capability::ShaderViewportIndex, spv::Capability::ShaderViewportIndexLayerEXT, spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
|
||||
static const spv::Capability pygen_variable_caps_OptNoneINTEL[] = {spv::Capability::OptNoneINTEL};
|
||||
static const spv::Capability pygen_variable_caps_PerViewAttributesNVMeshShadingNV[] = {spv::Capability::PerViewAttributesNV, spv::Capability::MeshShadingNV};
|
||||
static const spv::Capability pygen_variable_caps_PhysicalStorageBufferAddresses[] = {spv::Capability::PhysicalStorageBufferAddresses};
|
||||
static const spv::Capability pygen_variable_caps_Pipes[] = {spv::Capability::Pipes};
|
||||
static const spv::Capability pygen_variable_caps_RayCullMaskKHR[] = {spv::Capability::RayCullMaskKHR};
|
||||
static const spv::Capability pygen_variable_caps_RayQueryKHR[] = {spv::Capability::RayQueryKHR};
|
||||
static const spv::Capability pygen_variable_caps_RayQueryKHRRayTracingKHR[] = {spv::Capability::RayQueryKHR, spv::Capability::RayTracingKHR};
|
||||
static const spv::Capability pygen_variable_caps_RayTracingKHR[] = {spv::Capability::RayTracingKHR};
|
||||
static const spv::Capability pygen_variable_caps_RayTracingMotionBlurNV[] = {spv::Capability::RayTracingMotionBlurNV};
|
||||
static const spv::Capability pygen_variable_caps_RayTracingNV[] = {spv::Capability::RayTracingNV};
|
||||
static const spv::Capability pygen_variable_caps_RayTracingNVRayTracingKHR[] = {spv::Capability::RayTracingNV, spv::Capability::RayTracingKHR};
|
||||
static const spv::Capability pygen_variable_caps_RayTracingOpacityMicromapEXT[] = {spv::Capability::RayTracingOpacityMicromapEXT};
|
||||
static const spv::Capability pygen_variable_caps_RayTraversalPrimitiveCullingKHR[] = {spv::Capability::RayTraversalPrimitiveCullingKHR};
|
||||
static const spv::Capability pygen_variable_caps_RoundToInfinityINTEL[] = {spv::Capability::RoundToInfinityINTEL};
|
||||
static const spv::Capability pygen_variable_caps_RoundingModeRTE[] = {spv::Capability::RoundingModeRTE};
|
||||
static const spv::Capability pygen_variable_caps_RoundingModeRTZ[] = {spv::Capability::RoundingModeRTZ};
|
||||
static const spv::Capability pygen_variable_caps_RuntimeAlignedAttributeINTEL[] = {spv::Capability::RuntimeAlignedAttributeINTEL};
|
||||
static const spv::Capability pygen_variable_caps_SampleMaskOverrideCoverageNV[] = {spv::Capability::SampleMaskOverrideCoverageNV};
|
||||
static const spv::Capability pygen_variable_caps_SampleMaskPostDepthCoverage[] = {spv::Capability::SampleMaskPostDepthCoverage};
|
||||
static const spv::Capability pygen_variable_caps_SampleRateShading[] = {spv::Capability::SampleRateShading};
|
||||
static const spv::Capability pygen_variable_caps_Sampled1D[] = {spv::Capability::Sampled1D};
|
||||
static const spv::Capability pygen_variable_caps_Sampled1DImage1D[] = {spv::Capability::Sampled1D, spv::Capability::Image1D};
|
||||
static const spv::Capability pygen_variable_caps_SampledBuffer[] = {spv::Capability::SampledBuffer};
|
||||
static const spv::Capability pygen_variable_caps_SampledBufferImageBuffer[] = {spv::Capability::SampledBuffer, spv::Capability::ImageBuffer};
|
||||
static const spv::Capability pygen_variable_caps_SampledBufferShaderNonUniform[] = {spv::Capability::SampledBuffer, spv::Capability::ShaderNonUniform};
|
||||
static const spv::Capability pygen_variable_caps_SampledCubeArray[] = {spv::Capability::SampledCubeArray};
|
||||
static const spv::Capability pygen_variable_caps_SampledRect[] = {spv::Capability::SampledRect};
|
||||
static const spv::Capability pygen_variable_caps_SampledRectImageRect[] = {spv::Capability::SampledRect, spv::Capability::ImageRect};
|
||||
static const spv::Capability pygen_variable_caps_Shader[] = {spv::Capability::Shader};
|
||||
static const spv::Capability pygen_variable_caps_ShaderImageCubeArray[] = {spv::Capability::Shader, spv::Capability::ImageCubeArray};
|
||||
static const spv::Capability pygen_variable_caps_ShaderKernel[] = {spv::Capability::Shader, spv::Capability::Kernel};
|
||||
static const spv::Capability pygen_variable_caps_ShaderKernelImageMSArray[] = {spv::Capability::Shader, spv::Capability::Kernel, spv::Capability::ImageMSArray};
|
||||
static const spv::Capability pygen_variable_caps_ShaderUniformDecoration[] = {spv::Capability::Shader, spv::Capability::UniformDecoration};
|
||||
static const spv::Capability pygen_variable_caps_ShaderVectorComputeINTEL[] = {spv::Capability::Shader, spv::Capability::VectorComputeINTEL};
|
||||
static const spv::Capability pygen_variable_caps_ShaderInvocationReorderNV[] = {spv::Capability::ShaderInvocationReorderNV};
|
||||
static const spv::Capability pygen_variable_caps_ShaderNonUniform[] = {spv::Capability::ShaderNonUniform};
|
||||
static const spv::Capability pygen_variable_caps_ShaderSMBuiltinsNV[] = {spv::Capability::ShaderSMBuiltinsNV};
|
||||
static const spv::Capability pygen_variable_caps_ShaderStereoViewNV[] = {spv::Capability::ShaderStereoViewNV};
|
||||
static const spv::Capability pygen_variable_caps_ShaderViewportIndexLayerNV[] = {spv::Capability::ShaderViewportIndexLayerNV};
|
||||
static const spv::Capability pygen_variable_caps_ShaderViewportMaskNV[] = {spv::Capability::ShaderViewportMaskNV};
|
||||
static const spv::Capability pygen_variable_caps_ShaderViewportMaskNVMeshShadingNV[] = {spv::Capability::ShaderViewportMaskNV, spv::Capability::MeshShadingNV};
|
||||
static const spv::Capability pygen_variable_caps_ShadingRateNVFragmentDensityEXT[] = {spv::Capability::ShadingRateNV, spv::Capability::FragmentDensityEXT};
|
||||
static const spv::Capability pygen_variable_caps_SignedZeroInfNanPreserve[] = {spv::Capability::SignedZeroInfNanPreserve};
|
||||
static const spv::Capability pygen_variable_caps_StencilExportEXT[] = {spv::Capability::StencilExportEXT};
|
||||
static const spv::Capability pygen_variable_caps_StorageBuffer16BitAccessStorageUniformBufferBlock16[] = {spv::Capability::StorageBuffer16BitAccess, spv::Capability::StorageUniformBufferBlock16};
|
||||
static const spv::Capability pygen_variable_caps_StorageBuffer8BitAccess[] = {spv::Capability::StorageBuffer8BitAccess};
|
||||
static const spv::Capability pygen_variable_caps_StorageImageExtendedFormats[] = {spv::Capability::StorageImageExtendedFormats};
|
||||
static const spv::Capability pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot[] = {spv::Capability::SubgroupBallotKHR, spv::Capability::GroupNonUniformBallot};
|
||||
static const spv::Capability pygen_variable_caps_SubgroupDispatch[] = {spv::Capability::SubgroupDispatch};
|
||||
static const spv::Capability pygen_variable_caps_Tessellation[] = {spv::Capability::Tessellation};
|
||||
static const spv::Capability pygen_variable_caps_TransformFeedback[] = {spv::Capability::TransformFeedback};
|
||||
static const spv::Capability pygen_variable_caps_USMStorageClassesINTEL[] = {spv::Capability::USMStorageClassesINTEL};
|
||||
static const spv::Capability pygen_variable_caps_VariablePointersStorageBuffer[] = {spv::Capability::VariablePointersStorageBuffer};
|
||||
static const spv::Capability pygen_variable_caps_VectorAnyINTEL[] = {spv::Capability::VectorAnyINTEL};
|
||||
static const spv::Capability pygen_variable_caps_VectorComputeINTEL[] = {spv::Capability::VectorComputeINTEL};
|
||||
static const spv::Capability pygen_variable_caps_VulkanMemoryModel[] = {spv::Capability::VulkanMemoryModel};
|
||||
static const spv::Capability pygen_variable_caps_WorkgroupMemoryExplicitLayoutKHR[] = {spv::Capability::WorkgroupMemoryExplicitLayoutKHR};
|
||||
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_AMD_gpu_shader_half_float_fetch[] = {spvtools::Extension::kSPV_AMD_gpu_shader_half_float_fetch};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_ballot[] = {spvtools::Extension::kSPV_AMD_shader_ballot};
|
||||
@@ -162,6 +166,8 @@ static const spvtools::Extension pygen_variable_exts_SPV_INTEL_float_controls2[]
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fp_fast_math_mode[] = {spvtools::Extension::kSPV_INTEL_fp_fast_math_mode};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_buffer_location[] = {spvtools::Extension::kSPV_INTEL_fpga_buffer_location};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_cluster_attributes[] = {spvtools::Extension::kSPV_INTEL_fpga_cluster_attributes};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_dsp_control[] = {spvtools::Extension::kSPV_INTEL_fpga_dsp_control};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_invocation_pipelining_attributes[] = {spvtools::Extension::kSPV_INTEL_fpga_invocation_pipelining_attributes};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_loop_controls[] = {spvtools::Extension::kSPV_INTEL_fpga_loop_controls};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_memory_accesses[] = {spvtools::Extension::kSPV_INTEL_fpga_memory_accesses};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_memory_attributes[] = {spvtools::Extension::kSPV_INTEL_fpga_memory_attributes};
|
||||
@@ -175,6 +181,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_INTEL_loop_fuse[] = {sp
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_media_block_io[] = {spvtools::Extension::kSPV_INTEL_media_block_io};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_memory_access_aliasing[] = {spvtools::Extension::kSPV_INTEL_memory_access_aliasing};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_optnone[] = {spvtools::Extension::kSPV_INTEL_optnone};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_runtime_aligned[] = {spvtools::Extension::kSPV_INTEL_runtime_aligned};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_shader_integer_functions2[] = {spvtools::Extension::kSPV_INTEL_shader_integer_functions2};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_split_barrier[] = {spvtools::Extension::kSPV_INTEL_split_barrier};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_subgroups[] = {spvtools::Extension::kSPV_INTEL_subgroups};
|
||||
@@ -224,6 +231,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_NV_ray_tracing[] = {spv
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_ray_tracing_motion_blur[] = {spvtools::Extension::kSPV_NV_ray_tracing_motion_blur};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_sample_mask_override_coverage[] = {spvtools::Extension::kSPV_NV_sample_mask_override_coverage};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_image_footprint[] = {spvtools::Extension::kSPV_NV_shader_image_footprint};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_invocation_reorder[] = {spvtools::Extension::kSPV_NV_shader_invocation_reorder};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_sm_builtins[] = {spvtools::Extension::kSPV_NV_shader_sm_builtins};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_shader_subgroup_partitioned[] = {spvtools::Extension::kSPV_NV_shader_subgroup_partitioned};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_stereo_view_rendering[] = {spvtools::Extension::kSPV_NV_stereo_view_rendering};
|
||||
@@ -281,14 +289,16 @@ static const spv_operand_desc_t pygen_variable_LoopControlEntries[] = {
|
||||
{"IterationMultiple", 0x0040, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"PeelCount", 0x0080, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"PartialCount", 0x0100, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"InitiationIntervalINTEL", 0x10000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"MaxConcurrencyINTEL", 0x20000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"DependencyArrayINTEL", 0x40000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"PipelineEnableINTEL", 0x80000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"LoopCoalesceINTEL", 0x100000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"MaxInterleavingINTEL", 0x200000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"SpeculatedIterationsINTEL", 0x400000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"NoFusionINTEL", 0x800000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_loop_controls, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
|
||||
{"InitiationIntervalINTEL", 0x10000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"MaxConcurrencyINTEL", 0x20000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"DependencyArrayINTEL", 0x40000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"PipelineEnableINTEL", 0x80000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"LoopCoalesceINTEL", 0x100000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"MaxInterleavingINTEL", 0x200000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"SpeculatedIterationsINTEL", 0x400000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"NoFusionINTEL", 0x800000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"LoopCountINTEL", 0x1000000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"MaxReinvocationDelayINTEL", 0x2000000, 1, pygen_variable_caps_FPGALoopControlsINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_FunctionControlEntries[] = {
|
||||
@@ -495,6 +505,7 @@ static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = {
|
||||
{"NoGlobalOffsetINTEL", 5895, 1, pygen_variable_caps_KernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"NumSIMDWorkitemsINTEL", 5896, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"SchedulerTargetFmaxMhzINTEL", 5903, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"StreamingInterfaceINTEL", 6154, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"NamedBarrierCountINTEL", 6417, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}
|
||||
};
|
||||
|
||||
@@ -526,6 +537,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},
|
||||
{"HitObjectAttributeNV", 5385, 1, pygen_variable_caps_ShaderInvocationReorderNV, 0, nullptr, {}, 0xffffffffu, 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},
|
||||
@@ -698,7 +710,8 @@ static const spv_operand_desc_t pygen_variable_FunctionParameterAttributeEntries
|
||||
{"NoAlias", 4, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"NoCapture", 5, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"NoWrite", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"NoReadWrite", 7, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
|
||||
{"NoReadWrite", 7, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"RuntimeAlignedINTEL", 5940, 1, pygen_variable_caps_RuntimeAlignedAttributeINTEL, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
|
||||
@@ -768,6 +781,7 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
|
||||
{"RestrictPointerEXT", 5355, 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},
|
||||
{"AliasedPointer", 5356, 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},
|
||||
{"AliasedPointerEXT", 5356, 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},
|
||||
{"HitObjectShaderRecordBufferNV", 5386, 1, pygen_variable_caps_ShaderInvocationReorderNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BindlessSamplerNV", 5398, 1, pygen_variable_caps_BindlessTextureNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BindlessImageNV", 5399, 1, pygen_variable_caps_BindlessTextureNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BoundSamplerNV", 5400, 1, pygen_variable_caps_BindlessTextureNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
@@ -806,8 +820,12 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
|
||||
{"PrefetchINTEL", 5902, 1, pygen_variable_caps_FPGAMemoryAccessesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"StallEnableINTEL", 5905, 1, pygen_variable_caps_FPGAClusterAttributesINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FuseLoopsInFunctionINTEL", 5907, 1, pygen_variable_caps_LoopFuseINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"MathOpDSPModeINTEL", 5909, 1, pygen_variable_caps_FPGADSPControlINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"AliasScopeINTEL", 5914, 1, pygen_variable_caps_MemoryAccessAliasingINTEL, 0, nullptr, {SPV_OPERAND_TYPE_ID}, 0xffffffffu, 0xffffffffu},
|
||||
{"NoAliasINTEL", 5915, 1, pygen_variable_caps_MemoryAccessAliasingINTEL, 0, nullptr, {SPV_OPERAND_TYPE_ID}, 0xffffffffu, 0xffffffffu},
|
||||
{"InitiationIntervalINTEL", 5917, 1, pygen_variable_caps_FPGAInvocationPipeliningAttributesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"MaxConcurrencyINTEL", 5918, 1, pygen_variable_caps_FPGAInvocationPipeliningAttributesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"PipelineEnableINTEL", 5919, 1, pygen_variable_caps_FPGAInvocationPipeliningAttributesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"BufferLocationINTEL", 5921, 1, pygen_variable_caps_FPGABufferLocationINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"IOPipeStorageINTEL", 5944, 1, pygen_variable_caps_IOPipesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"FunctionFloatingPointModeINTEL", 6080, 1, pygen_variable_caps_FunctionFloatControlINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_FPOPERATION_MODE}, 0xffffffffu, 0xffffffffu},
|
||||
@@ -1146,6 +1164,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"DemoteToHelperInvocation", 5379, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DemoteToHelperInvocationEXT", 5379, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"RayTracingOpacityMicromapEXT", 5381, 2, pygen_variable_caps_RayQueryKHRRayTracingKHR, 1, pygen_variable_exts_SPV_EXT_opacity_micromap, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ShaderInvocationReorderNV", 5383, 1, pygen_variable_caps_RayTracingKHR, 1, pygen_variable_exts_SPV_NV_shader_invocation_reorder, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BindlessTextureNV", 5390, 0, nullptr, 1, pygen_variable_exts_SPV_NV_bindless_texture, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupShuffleINTEL", 5568, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupBufferBlockIOINTEL", 5569, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
|
||||
@@ -1179,10 +1198,13 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"FPGAMemoryAccessesINTEL", 5898, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_memory_accesses, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FPGAClusterAttributesINTEL", 5904, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_cluster_attributes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"LoopFuseINTEL", 5906, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_loop_fuse, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FPGADSPControlINTEL", 5908, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_dsp_control, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"MemoryAccessAliasingINTEL", 5910, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_memory_access_aliasing, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FPGAInvocationPipeliningAttributesINTEL", 5916, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_invocation_pipelining_attributes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FPGABufferLocationINTEL", 5920, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_buffer_location, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ArbitraryPrecisionFixedPointINTEL", 5922, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_arbitrary_precision_fixed_point, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"USMStorageClassesINTEL", 5935, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_usm_storage_classes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"RuntimeAlignedAttributeINTEL", 5939, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_runtime_aligned, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"IOPipesINTEL", 5943, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_io_pipes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BlockingPipesINTEL", 5945, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_blocking_pipes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FPGARegINTEL", 5948, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_reg, {}, 0xffffffffu, 0xffffffffu},
|
||||
|
||||
@@ -36,16 +36,25 @@ namespace spvtools {
|
||||
// generated by InstrumentPass::GenDebugStreamWrite. This method is utilized
|
||||
// by InstBindlessCheckPass, InstBuffAddrCheckPass, and InstDebugPrintfPass.
|
||||
//
|
||||
// The first member of the debug output buffer contains the next available word
|
||||
// The 1st member of the debug output buffer contains a set of flags
|
||||
// controlling the behavior of instrumentation code.
|
||||
static const int kDebugOutputFlagsOffset = 0;
|
||||
|
||||
// Values stored at kDebugOutputFlagsOffset
|
||||
enum kInstFlags : unsigned int {
|
||||
kInstBufferOOBEnable = 0x1,
|
||||
};
|
||||
|
||||
// The 2nd member of the debug output buffer contains the next available word
|
||||
// in the data stream to be written. Shaders will atomically read and update
|
||||
// this value so as not to overwrite each others records. This value must be
|
||||
// initialized to zero
|
||||
static const int kDebugOutputSizeOffset = 0;
|
||||
static const int kDebugOutputSizeOffset = 1;
|
||||
|
||||
// The second member of the output buffer is the start of the stream of records
|
||||
// The 3rd member of the output buffer is the start of the stream of records
|
||||
// written by the instrumented shaders. Each record represents a validation
|
||||
// error. The format of the records is documented below.
|
||||
static const int kDebugOutputDataOffset = 1;
|
||||
static const int kDebugOutputDataOffset = 2;
|
||||
|
||||
// Common Stream Record Offsets
|
||||
//
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -520,8 +521,12 @@ Optimizer::PassToken CreateDeadInsertElimPass();
|
||||
// interface are considered live and are not eliminated. This mode is needed
|
||||
// by GPU-Assisted validation instrumentation, where a change in the interface
|
||||
// is not allowed.
|
||||
Optimizer::PassToken CreateAggressiveDCEPass();
|
||||
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface);
|
||||
//
|
||||
// If |remove_outputs| is true, allow outputs to be removed from the interface.
|
||||
// This is only safe if the caller knows that there is no corresponding input
|
||||
// variable in the following shader. It is false by default.
|
||||
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface = false,
|
||||
bool remove_outputs = false);
|
||||
|
||||
// Creates a remove-unused-interface-variables pass.
|
||||
// Removes variables referenced on the |OpEntryPoint| instruction that are not
|
||||
@@ -887,12 +892,59 @@ Optimizer::PassToken CreateAmdExtToKhrPass();
|
||||
Optimizer::PassToken CreateInterpolateFixupPass();
|
||||
|
||||
// Removes unused components from composite input variables. Current
|
||||
// implementation just removes trailing unused components from input arrays.
|
||||
// The pass performs best after maximizing dead code removal. A subsequent dead
|
||||
// code elimination pass would be beneficial in removing newly unused component
|
||||
// types.
|
||||
// implementation just removes trailing unused components from input arrays
|
||||
// and structs. The pass performs best after maximizing dead code removal.
|
||||
// A subsequent dead code elimination pass would be beneficial in removing
|
||||
// newly unused component types.
|
||||
//
|
||||
// WARNING: This pass can only be safely applied standalone to vertex shaders
|
||||
// as it can otherwise cause interface incompatibilities with the preceding
|
||||
// shader in the pipeline. If applied to non-vertex shaders, the user should
|
||||
// follow by applying EliminateDeadOutputStores and
|
||||
// EliminateDeadOutputComponents to the preceding shader.
|
||||
Optimizer::PassToken CreateEliminateDeadInputComponentsPass();
|
||||
|
||||
// Removes unused components from composite output variables. Current
|
||||
// implementation just removes trailing unused components from output arrays
|
||||
// and structs. The pass performs best after eliminating dead output stores.
|
||||
// A subsequent dead code elimination pass would be beneficial in removing
|
||||
// newly unused component types. Currently only supports vertex and fragment
|
||||
// shaders.
|
||||
//
|
||||
// WARNING: This pass cannot be safely applied standalone as it can cause
|
||||
// interface incompatibility with the following shader in the pipeline. The
|
||||
// user should first apply EliminateDeadInputComponents to the following
|
||||
// shader, then apply EliminateDeadOutputStores to this shader.
|
||||
Optimizer::PassToken CreateEliminateDeadOutputComponentsPass();
|
||||
|
||||
// Removes unused components from composite input variables. This safe
|
||||
// version will not cause interface incompatibilities since it only changes
|
||||
// vertex shaders. The current implementation just removes trailing unused
|
||||
// components from input structs and input arrays. The pass performs best
|
||||
// after maximizing dead code removal. A subsequent dead code elimination
|
||||
// pass would be beneficial in removing newly unused component types.
|
||||
Optimizer::PassToken CreateEliminateDeadInputComponentsSafePass();
|
||||
|
||||
// Analyzes shader and populates |live_locs| and |live_builtins|. Best results
|
||||
// will be obtained if shader has all dead code eliminated first. |live_locs|
|
||||
// and |live_builtins| are subsequently used when calling
|
||||
// CreateEliminateDeadOutputStoresPass on the preceding shader. Currently only
|
||||
// supports tesc, tese, geom, and frag shaders.
|
||||
Optimizer::PassToken CreateAnalyzeLiveInputPass(
|
||||
std::unordered_set<uint32_t>* live_locs,
|
||||
std::unordered_set<uint32_t>* live_builtins);
|
||||
|
||||
// Removes stores to output locations not listed in |live_locs| or
|
||||
// |live_builtins|. Best results are obtained if constant propagation is
|
||||
// performed first. A subsequent call to ADCE will eliminate any dead code
|
||||
// created by the removal of the stores. A subsequent call to
|
||||
// CreateEliminateDeadOutputComponentsPass will eliminate any dead output
|
||||
// components created by the elimination of the stores. Currently only supports
|
||||
// vert, tesc, tese, and geom shaders.
|
||||
Optimizer::PassToken CreateEliminateDeadOutputStoresPass(
|
||||
std::unordered_set<uint32_t>* live_locs,
|
||||
std::unordered_set<uint32_t>* live_builtins);
|
||||
|
||||
// Creates a convert-to-sampled-image pass to convert images and/or
|
||||
// samplers with given pairs of descriptor set and binding to sampled image.
|
||||
// If a pair of an image and a sampler have the same pair of descriptor set and
|
||||
|
||||
16
3rdparty/spirv-tools/source/assembly_grammar.cpp
vendored
16
3rdparty/spirv-tools/source/assembly_grammar.cpp
vendored
@@ -78,16 +78,16 @@ spv_result_t spvTextParseMaskOperand(spv_target_env env,
|
||||
|
||||
// Associates an opcode with its name.
|
||||
struct SpecConstantOpcodeEntry {
|
||||
SpvOp opcode;
|
||||
spv::Op opcode;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
// All the opcodes allowed as the operation for OpSpecConstantOp.
|
||||
// The name does not have the usual "Op" prefix. For example opcode SpvOpIAdd
|
||||
// is associated with the name "IAdd".
|
||||
// The name does not have the usual "Op" prefix. For example opcode
|
||||
// spv::Op::IAdd is associated with the name "IAdd".
|
||||
//
|
||||
// clang-format off
|
||||
#define CASE(NAME) { SpvOp##NAME, #NAME }
|
||||
#define CASE(NAME) { spv::Op::Op##NAME, #NAME }
|
||||
const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
|
||||
// Conversion
|
||||
CASE(SConvert),
|
||||
@@ -173,7 +173,7 @@ bool AssemblyGrammar::isValid() const {
|
||||
}
|
||||
|
||||
CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv(
|
||||
const SpvCapability* cap_array, uint32_t count) const {
|
||||
const spv::Capability* cap_array, uint32_t count) const {
|
||||
CapabilitySet cap_set;
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
spv_operand_desc cap_desc = {};
|
||||
@@ -194,7 +194,7 @@ spv_result_t AssemblyGrammar::lookupOpcode(const char* name,
|
||||
return spvOpcodeTableNameLookup(target_env_, opcodeTable_, name, desc);
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupOpcode(SpvOp opcode,
|
||||
spv_result_t AssemblyGrammar::lookupOpcode(spv::Op opcode,
|
||||
spv_opcode_desc* desc) const {
|
||||
return spvOpcodeTableValueLookup(target_env_, opcodeTable_, opcode, desc);
|
||||
}
|
||||
@@ -214,7 +214,7 @@ spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
|
||||
SpvOp* opcode) const {
|
||||
spv::Op* opcode) const {
|
||||
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
||||
const auto* found =
|
||||
std::find_if(kOpSpecConstantOpcodes, last,
|
||||
@@ -226,7 +226,7 @@ spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(SpvOp opcode) const {
|
||||
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(spv::Op opcode) const {
|
||||
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
||||
const auto* found =
|
||||
std::find_if(kOpSpecConstantOpcodes, last,
|
||||
|
||||
@@ -41,7 +41,7 @@ class AssemblyGrammar {
|
||||
|
||||
// Removes capabilities not available in the current target environment and
|
||||
// returns the rest.
|
||||
CapabilitySet filterCapsAgainstTargetEnv(const SpvCapability* cap_array,
|
||||
CapabilitySet filterCapsAgainstTargetEnv(const spv::Capability* cap_array,
|
||||
uint32_t count) const;
|
||||
|
||||
// Fills in the desc parameter with the information about the opcode
|
||||
@@ -52,7 +52,7 @@ class AssemblyGrammar {
|
||||
// Fills in the desc parameter with the information about the opcode
|
||||
// of the valid. Returns SPV_SUCCESS if the opcode was found, and
|
||||
// SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
|
||||
spv_result_t lookupOpcode(SpvOp opcode, spv_opcode_desc* desc) const;
|
||||
spv_result_t lookupOpcode(spv::Op opcode, spv_opcode_desc* desc) const;
|
||||
|
||||
// Fills in the desc parameter with the information about the given
|
||||
// operand. Returns SPV_SUCCESS if the operand was found, and
|
||||
@@ -82,11 +82,12 @@ class AssemblyGrammar {
|
||||
// the integer add opcode for OpSpecConstantOp. On success, returns
|
||||
// SPV_SUCCESS and sends the discovered operation code through the opcode
|
||||
// parameter. On failure, returns SPV_ERROR_INVALID_LOOKUP.
|
||||
spv_result_t lookupSpecConstantOpcode(const char* name, SpvOp* opcode) const;
|
||||
spv_result_t lookupSpecConstantOpcode(const char* name,
|
||||
spv::Op* opcode) const;
|
||||
|
||||
// Returns SPV_SUCCESS if the given opcode is valid as the opcode operand
|
||||
// to OpSpecConstantOp.
|
||||
spv_result_t lookupSpecConstantOpcode(SpvOp opcode) const;
|
||||
spv_result_t lookupSpecConstantOpcode(spv::Op opcode) const;
|
||||
|
||||
// Parses a mask expression string for the given operand type.
|
||||
//
|
||||
|
||||
31
3rdparty/spirv-tools/source/binary.cpp
vendored
31
3rdparty/spirv-tools/source/binary.cpp
vendored
@@ -156,7 +156,7 @@ class Parser {
|
||||
// Issues a diagnostic describing an exhaustion of input condition when
|
||||
// trying to decode an instruction operand, and returns
|
||||
// SPV_ERROR_INVALID_BINARY.
|
||||
spv_result_t exhaustedInputDiagnostic(size_t inst_offset, SpvOp opcode,
|
||||
spv_result_t exhaustedInputDiagnostic(size_t inst_offset, spv::Op opcode,
|
||||
spv_operand_type_t type) {
|
||||
return diagnostic() << "End of input reached while decoding Op"
|
||||
<< spvOpcodeString(opcode) << " starting at word "
|
||||
@@ -318,7 +318,7 @@ spv_result_t Parser::parseInstruction() {
|
||||
<< inst_word_count;
|
||||
}
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (grammar_.lookupOpcode(static_cast<SpvOp>(inst.opcode), &opcode_desc))
|
||||
if (grammar_.lookupOpcode(static_cast<spv::Op>(inst.opcode), &opcode_desc))
|
||||
return diagnostic() << "Invalid opcode: " << inst.opcode;
|
||||
|
||||
// Advance past the opcode word. But remember the of the start
|
||||
@@ -418,7 +418,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
std::vector<uint32_t>* words,
|
||||
std::vector<spv_parsed_operand_t>* operands,
|
||||
spv_operand_pattern_t* expected_operands) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
|
||||
// We'll fill in this result as we go along.
|
||||
spv_parsed_operand_t parsed_operand;
|
||||
parsed_operand.offset = uint16_t(_.word_index - inst_offset);
|
||||
@@ -473,7 +473,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_ID;
|
||||
|
||||
if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
|
||||
if (opcode == spv::Op::OpExtInst && parsed_operand.offset == 3) {
|
||||
// The current word is the extended instruction set Id.
|
||||
// Set the extended instruction set type for the current instruction.
|
||||
auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
|
||||
@@ -494,7 +494,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
||||
assert(SpvOpExtInst == opcode);
|
||||
assert(spv::Op::OpExtInst == opcode);
|
||||
assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
|
||||
spv_ext_inst_desc ext_inst;
|
||||
if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) ==
|
||||
@@ -516,14 +516,14 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
} break;
|
||||
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||
assert(SpvOpSpecConstantOp == opcode);
|
||||
if (word > static_cast<uint32_t>(SpvOp::SpvOpMax) ||
|
||||
grammar_.lookupSpecConstantOpcode(SpvOp(word))) {
|
||||
assert(spv::Op::OpSpecConstantOp == opcode);
|
||||
if (word > static_cast<uint32_t>(spv::Op::Max) ||
|
||||
grammar_.lookupSpecConstantOpcode(spv::Op(word))) {
|
||||
return diagnostic()
|
||||
<< "Invalid " << spvOperandTypeStr(type) << ": " << word;
|
||||
}
|
||||
spv_opcode_desc opcode_entry = nullptr;
|
||||
if (grammar_.lookupOpcode(SpvOp(word), &opcode_entry)) {
|
||||
if (grammar_.lookupOpcode(spv::Op(word), &opcode_entry)) {
|
||||
return diagnostic(SPV_ERROR_INTERNAL)
|
||||
<< "OpSpecConstant opcode table out of sync";
|
||||
}
|
||||
@@ -549,7 +549,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
|
||||
if (opcode == SpvOpSwitch) {
|
||||
if (opcode == spv::Op::OpSwitch) {
|
||||
// The literal operands have the same type as the value
|
||||
// referenced by the selector Id.
|
||||
const uint32_t selector_id = peekAt(inst_offset + 1);
|
||||
@@ -575,7 +575,8 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
<< " is not a scalar integer";
|
||||
}
|
||||
} else {
|
||||
assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant);
|
||||
assert(opcode == spv::Op::OpConstant ||
|
||||
opcode == spv::Op::OpSpecConstant);
|
||||
// The literal number type is determined by the type Id for the
|
||||
// constant.
|
||||
assert(inst->type_id);
|
||||
@@ -607,7 +608,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
parsed_operand.num_words = uint16_t(string_num_words);
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
|
||||
|
||||
if (SpvOpExtInstImport == opcode) {
|
||||
if (spv::Op::OpExtInstImport == opcode) {
|
||||
// Record the extended instruction type for the ID for this import.
|
||||
// There is only one string literal argument to OpExtInstImport,
|
||||
// so it's sufficient to guard this just on the opcode.
|
||||
@@ -789,14 +790,14 @@ spv_result_t Parser::setNumericTypeInfoForType(
|
||||
|
||||
void Parser::recordNumberType(size_t inst_offset,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
|
||||
if (spvOpcodeGeneratesType(opcode)) {
|
||||
NumberType info = {SPV_NUMBER_NONE, 0};
|
||||
if (SpvOpTypeInt == opcode) {
|
||||
if (spv::Op::OpTypeInt == opcode) {
|
||||
const bool is_signed = peekAt(inst_offset + 3) != 0;
|
||||
info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
|
||||
info.bit_width = peekAt(inst_offset + 2);
|
||||
} else if (SpvOpTypeFloat == opcode) {
|
||||
} else if (spv::Op::OpTypeFloat == opcode) {
|
||||
info.type = SPV_NUMBER_FLOATING;
|
||||
info.bit_width = peekAt(inst_offset + 2);
|
||||
}
|
||||
|
||||
325
3rdparty/spirv-tools/source/diff/diff.cpp
vendored
325
3rdparty/spirv-tools/source/diff/diff.cpp
vendored
@@ -44,8 +44,8 @@ using IdGroup = std::vector<uint32_t>;
|
||||
// different implementations produce identical results.
|
||||
using IdGroupMapByName = std::map<std::string, IdGroup>;
|
||||
using IdGroupMapByTypeId = std::map<uint32_t, IdGroup>;
|
||||
using IdGroupMapByOp = std::map<SpvOp, IdGroup>;
|
||||
using IdGroupMapByStorageClass = std::map<SpvStorageClass, IdGroup>;
|
||||
using IdGroupMapByOp = std::map<spv::Op, IdGroup>;
|
||||
using IdGroupMapByStorageClass = std::map<spv::StorageClass, IdGroup>;
|
||||
|
||||
// A set of potential id mappings that haven't been resolved yet. Any id in src
|
||||
// may map in any id in dst. Note that ids are added in the same order as they
|
||||
@@ -301,10 +301,10 @@ class Differ {
|
||||
// Get various properties from an id. These Helper functions are passed to
|
||||
// `GroupIds` and `GroupIdsAndMatch` below (as the `get_group` argument).
|
||||
uint32_t GroupIdsHelperGetTypeId(const IdInstructions& id_to, uint32_t id);
|
||||
SpvStorageClass GroupIdsHelperGetTypePointerStorageClass(
|
||||
spv::StorageClass GroupIdsHelperGetTypePointerStorageClass(
|
||||
const IdInstructions& id_to, uint32_t id);
|
||||
SpvOp GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
|
||||
uint32_t id);
|
||||
spv::Op GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
|
||||
uint32_t id);
|
||||
|
||||
// Given a list of ids, groups them based on some value. The `get_group`
|
||||
// function extracts a piece of information corresponding to each id, and the
|
||||
@@ -414,8 +414,8 @@ class Differ {
|
||||
// Helper functions to retrieve information pertaining to an id
|
||||
const opt::Instruction* GetInst(const IdInstructions& id_to, uint32_t id);
|
||||
uint32_t GetConstantUint(const IdInstructions& id_to, uint32_t constant_id);
|
||||
SpvExecutionModel GetExecutionModel(const opt::Module* module,
|
||||
uint32_t entry_point_id);
|
||||
spv::ExecutionModel GetExecutionModel(const opt::Module* module,
|
||||
uint32_t entry_point_id);
|
||||
bool HasName(const IdInstructions& id_to, uint32_t id);
|
||||
// Get the OpName associated with an id
|
||||
std::string GetName(const IdInstructions& id_to, uint32_t id, bool* has_name);
|
||||
@@ -424,20 +424,21 @@ class Differ {
|
||||
// string, and this improves diff between SPIR-V from those tools and others.
|
||||
std::string GetSanitizedName(const IdInstructions& id_to, uint32_t id);
|
||||
uint32_t GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
|
||||
SpvStorageClass* storage_class);
|
||||
spv::StorageClass* storage_class);
|
||||
bool GetDecorationValue(const IdInstructions& id_to, uint32_t id,
|
||||
SpvDecoration decoration, uint32_t* decoration_value);
|
||||
spv::Decoration decoration,
|
||||
uint32_t* decoration_value);
|
||||
const opt::Instruction* GetForwardPointerInst(const IdInstructions& id_to,
|
||||
uint32_t id);
|
||||
bool IsIntType(const IdInstructions& id_to, uint32_t type_id);
|
||||
bool IsFloatType(const IdInstructions& id_to, uint32_t type_id);
|
||||
bool IsConstantUint(const IdInstructions& id_to, uint32_t id);
|
||||
bool IsVariable(const IdInstructions& id_to, uint32_t pointer_id);
|
||||
bool IsOp(const IdInstructions& id_to, uint32_t id, SpvOp opcode);
|
||||
bool IsOp(const IdInstructions& id_to, uint32_t id, spv::Op opcode);
|
||||
bool IsPerVertexType(const IdInstructions& id_to, uint32_t type_id);
|
||||
bool IsPerVertexVariable(const IdInstructions& id_to, uint32_t type_id);
|
||||
SpvStorageClass GetPerVertexStorageClass(const opt::Module* module,
|
||||
uint32_t type_id);
|
||||
spv::StorageClass GetPerVertexStorageClass(const opt::Module* module,
|
||||
uint32_t type_id);
|
||||
spv_ext_inst_type_t GetExtInstType(const IdInstructions& id_to,
|
||||
uint32_t set_id);
|
||||
spv_number_kind_t GetNumberKind(const IdInstructions& id_to,
|
||||
@@ -561,19 +562,19 @@ void IdInstructions::MapIdsToInfos(
|
||||
uint32_t id_operand = 0;
|
||||
|
||||
switch (inst.opcode()) {
|
||||
case SpvOpName:
|
||||
case spv::Op::OpName:
|
||||
info_map = &name_map_;
|
||||
break;
|
||||
case SpvOpMemberName:
|
||||
case spv::Op::OpMemberName:
|
||||
info_map = &name_map_;
|
||||
break;
|
||||
case SpvOpDecorate:
|
||||
case spv::Op::OpDecorate:
|
||||
info_map = &decoration_map_;
|
||||
break;
|
||||
case SpvOpMemberDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
info_map = &decoration_map_;
|
||||
break;
|
||||
case SpvOpTypeForwardPointer: {
|
||||
case spv::Op::OpTypeForwardPointer: {
|
||||
uint32_t id = inst.GetSingleWordOperand(0);
|
||||
assert(id != 0);
|
||||
|
||||
@@ -731,10 +732,10 @@ int Differ::ComparePreambleInstructions(const opt::Instruction* a,
|
||||
// Instead of comparing OpExecutionMode entry point ids as ids, compare them
|
||||
// through their corresponding execution model. This simplifies traversing
|
||||
// the sorted list of instructions between src and dst modules.
|
||||
if (a->opcode() == SpvOpExecutionMode) {
|
||||
const SpvExecutionModel src_model =
|
||||
if (a->opcode() == spv::Op::OpExecutionMode) {
|
||||
const spv::ExecutionModel src_model =
|
||||
GetExecutionModel(src_inst_module, a->GetSingleWordOperand(0));
|
||||
const SpvExecutionModel dst_model =
|
||||
const spv::ExecutionModel dst_model =
|
||||
GetExecutionModel(dst_inst_module, b->GetSingleWordOperand(0));
|
||||
|
||||
if (src_model < dst_model) {
|
||||
@@ -818,17 +819,17 @@ uint32_t Differ::GroupIdsHelperGetTypeId(const IdInstructions& id_to,
|
||||
return GetInst(id_to, id)->type_id();
|
||||
}
|
||||
|
||||
SpvStorageClass Differ::GroupIdsHelperGetTypePointerStorageClass(
|
||||
spv::StorageClass Differ::GroupIdsHelperGetTypePointerStorageClass(
|
||||
const IdInstructions& id_to, uint32_t id) {
|
||||
const opt::Instruction* inst = GetInst(id_to, id);
|
||||
assert(inst && inst->opcode() == SpvOpTypePointer);
|
||||
return SpvStorageClass(inst->GetSingleWordInOperand(0));
|
||||
assert(inst && inst->opcode() == spv::Op::OpTypePointer);
|
||||
return spv::StorageClass(inst->GetSingleWordInOperand(0));
|
||||
}
|
||||
|
||||
SpvOp Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
|
||||
uint32_t id) {
|
||||
spv::Op Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
|
||||
uint32_t id) {
|
||||
const opt::Instruction* inst = GetInst(id_to, id);
|
||||
assert(inst && inst->opcode() == SpvOpTypePointer);
|
||||
assert(inst && inst->opcode() == spv::Op::OpTypePointer);
|
||||
|
||||
const uint32_t type_id = inst->GetSingleWordInOperand(1);
|
||||
const opt::Instruction* type_inst = GetInst(id_to, type_id);
|
||||
@@ -1020,7 +1021,7 @@ bool Differ::DoInstructionsMatchFuzzy(const opt::Instruction* src_inst,
|
||||
}
|
||||
// For external instructions, make sure the set and opcode of the external
|
||||
// instruction matches too.
|
||||
if (src_inst->opcode() == SpvOpExtInst) {
|
||||
if (src_inst->opcode() == spv::Op::OpExtInst) {
|
||||
if (!DoOperandsMatch(src_inst, dst_inst, 0, 2)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1064,26 +1065,26 @@ bool Differ::DoDebugAndAnnotationInstructionsMatch(
|
||||
}
|
||||
|
||||
switch (src_inst->opcode()) {
|
||||
case SpvOpString:
|
||||
case SpvOpSourceExtension:
|
||||
case SpvOpModuleProcessed:
|
||||
case spv::Op::OpString:
|
||||
case spv::Op::OpSourceExtension:
|
||||
case spv::Op::OpModuleProcessed:
|
||||
return DoesOperandMatch(src_inst->GetOperand(0), dst_inst->GetOperand(0));
|
||||
case SpvOpSource:
|
||||
case spv::Op::OpSource:
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0, 2);
|
||||
case SpvOpSourceContinued:
|
||||
case spv::Op::OpSourceContinued:
|
||||
return true;
|
||||
case SpvOpName:
|
||||
case spv::Op::OpName:
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0, 1);
|
||||
case SpvOpMemberName:
|
||||
case spv::Op::OpMemberName:
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0, 2);
|
||||
case SpvOpDecorate:
|
||||
case spv::Op::OpDecorate:
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0, 2);
|
||||
case SpvOpMemberDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0, 3);
|
||||
case SpvOpExtInst:
|
||||
case SpvOpDecorationGroup:
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case spv::Op::OpExtInst:
|
||||
case spv::Op::OpDecorationGroup:
|
||||
case spv::Op::OpGroupDecorate:
|
||||
case spv::Op::OpGroupMemberDecorate:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
@@ -1095,9 +1096,9 @@ bool Differ::AreVariablesMatchable(uint32_t src_id, uint32_t dst_id,
|
||||
// Variables must match by their built-in decorations.
|
||||
uint32_t src_built_in_decoration = 0, dst_built_in_decoration = 0;
|
||||
const bool src_is_built_in = GetDecorationValue(
|
||||
src_id_to_, src_id, SpvDecorationBuiltIn, &src_built_in_decoration);
|
||||
src_id_to_, src_id, spv::Decoration::BuiltIn, &src_built_in_decoration);
|
||||
const bool dst_is_built_in = GetDecorationValue(
|
||||
dst_id_to_, dst_id, SpvDecorationBuiltIn, &dst_built_in_decoration);
|
||||
dst_id_to_, dst_id, spv::Decoration::BuiltIn, &dst_built_in_decoration);
|
||||
|
||||
if (src_is_built_in != dst_is_built_in) {
|
||||
return false;
|
||||
@@ -1107,7 +1108,7 @@ bool Differ::AreVariablesMatchable(uint32_t src_id, uint32_t dst_id,
|
||||
}
|
||||
|
||||
// Check their types and storage classes.
|
||||
SpvStorageClass src_storage_class, dst_storage_class;
|
||||
spv::StorageClass src_storage_class, dst_storage_class;
|
||||
const uint32_t src_type_id =
|
||||
GetVarTypeId(src_id_to_, src_id, &src_storage_class);
|
||||
const uint32_t dst_type_id =
|
||||
@@ -1127,12 +1128,14 @@ bool Differ::AreVariablesMatchable(uint32_t src_id, uint32_t dst_id,
|
||||
// Allow one of the two to be Private while the other is Input or
|
||||
// Output, this allows matching in/out variables that have been turned
|
||||
// global as part of linking two stages (as done in ANGLE).
|
||||
const bool src_is_io = src_storage_class == SpvStorageClassInput ||
|
||||
src_storage_class == SpvStorageClassOutput;
|
||||
const bool dst_is_io = dst_storage_class == SpvStorageClassInput ||
|
||||
dst_storage_class == SpvStorageClassOutput;
|
||||
const bool src_is_private = src_storage_class == SpvStorageClassPrivate;
|
||||
const bool dst_is_private = dst_storage_class == SpvStorageClassPrivate;
|
||||
const bool src_is_io = src_storage_class == spv::StorageClass::Input ||
|
||||
src_storage_class == spv::StorageClass::Output;
|
||||
const bool dst_is_io = dst_storage_class == spv::StorageClass::Input ||
|
||||
dst_storage_class == spv::StorageClass::Output;
|
||||
const bool src_is_private =
|
||||
src_storage_class == spv::StorageClass::Private;
|
||||
const bool dst_is_private =
|
||||
dst_storage_class == spv::StorageClass::Private;
|
||||
|
||||
if (!((src_is_io && dst_is_private) || (src_is_private && dst_is_io))) {
|
||||
return false;
|
||||
@@ -1277,16 +1280,16 @@ bool Differ::MatchOpSpecConstant(const opt::Instruction* src_inst,
|
||||
// Otherwise, match them by SpecId.
|
||||
uint32_t src_spec_id, dst_spec_id;
|
||||
|
||||
if (GetDecorationValue(src_id_to_, src_id, SpvDecorationSpecId,
|
||||
if (GetDecorationValue(src_id_to_, src_id, spv::Decoration::SpecId,
|
||||
&src_spec_id) &&
|
||||
GetDecorationValue(dst_id_to_, dst_id, SpvDecorationSpecId,
|
||||
GetDecorationValue(dst_id_to_, dst_id, spv::Decoration::SpecId,
|
||||
&dst_spec_id)) {
|
||||
return src_spec_id == dst_spec_id;
|
||||
}
|
||||
|
||||
// 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->opcode() == spv::Op::OpSpecConstantOp) {
|
||||
if (src_inst->NumInOperandWords() == dst_inst->NumInOperandWords()) {
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0,
|
||||
src_inst->NumInOperandWords());
|
||||
@@ -1327,13 +1330,13 @@ bool Differ::MatchOpVariable(const opt::Instruction* src_inst,
|
||||
// built-in decorations.
|
||||
uint32_t src_built_in_decoration;
|
||||
const bool src_is_built_in = GetDecorationValue(
|
||||
src_id_to_, src_id, SpvDecorationBuiltIn, &src_built_in_decoration);
|
||||
src_id_to_, src_id, spv::Decoration::BuiltIn, &src_built_in_decoration);
|
||||
|
||||
if (src_is_built_in && AreVariablesMatchable(src_id, dst_id, flexibility)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SpvStorageClass src_storage_class, dst_storage_class;
|
||||
spv::StorageClass src_storage_class, dst_storage_class;
|
||||
GetVarTypeId(src_id_to_, src_id, &src_storage_class);
|
||||
GetVarTypeId(dst_id_to_, dst_id, &dst_storage_class);
|
||||
|
||||
@@ -1348,13 +1351,13 @@ bool Differ::MatchOpVariable(const opt::Instruction* src_inst,
|
||||
uint32_t src_binding = 0, dst_binding = 0;
|
||||
|
||||
const bool src_has_set = GetDecorationValue(
|
||||
src_id_to_, src_id, SpvDecorationDescriptorSet, &src_set);
|
||||
src_id_to_, src_id, spv::Decoration::DescriptorSet, &src_set);
|
||||
const bool dst_has_set = GetDecorationValue(
|
||||
dst_id_to_, dst_id, SpvDecorationDescriptorSet, &dst_set);
|
||||
const bool src_has_binding =
|
||||
GetDecorationValue(src_id_to_, src_id, SpvDecorationBinding, &src_set);
|
||||
const bool dst_has_binding =
|
||||
GetDecorationValue(dst_id_to_, dst_id, SpvDecorationBinding, &dst_set);
|
||||
dst_id_to_, dst_id, spv::Decoration::DescriptorSet, &dst_set);
|
||||
const bool src_has_binding = GetDecorationValue(
|
||||
src_id_to_, src_id, spv::Decoration::Binding, &src_set);
|
||||
const bool dst_has_binding = GetDecorationValue(
|
||||
dst_id_to_, dst_id, spv::Decoration::Binding, &dst_set);
|
||||
|
||||
if (src_has_set && dst_has_set && src_has_binding && dst_has_binding) {
|
||||
return src_set == dst_set && src_binding == dst_binding;
|
||||
@@ -1367,9 +1370,9 @@ bool Differ::MatchOpVariable(const opt::Instruction* src_inst,
|
||||
uint32_t src_location, dst_location;
|
||||
|
||||
const bool src_has_location = GetDecorationValue(
|
||||
src_id_to_, src_id, SpvDecorationLocation, &src_location);
|
||||
src_id_to_, src_id, spv::Decoration::Location, &src_location);
|
||||
const bool dst_has_location = GetDecorationValue(
|
||||
dst_id_to_, dst_id, SpvDecorationLocation, &dst_location);
|
||||
dst_id_to_, dst_id, spv::Decoration::Location, &dst_location);
|
||||
|
||||
if (src_has_location && dst_has_location) {
|
||||
return src_location == dst_location;
|
||||
@@ -1384,25 +1387,25 @@ bool Differ::MatchPerVertexType(uint32_t src_type_id, uint32_t dst_type_id) {
|
||||
// For gl_PerVertex, find the type pointer of this type (array) and make sure
|
||||
// the storage classes of src and dst match; geometry and tessellation shaders
|
||||
// have two instances of gl_PerVertex.
|
||||
SpvStorageClass src_storage_class =
|
||||
spv::StorageClass src_storage_class =
|
||||
GetPerVertexStorageClass(src_, src_type_id);
|
||||
SpvStorageClass dst_storage_class =
|
||||
spv::StorageClass dst_storage_class =
|
||||
GetPerVertexStorageClass(dst_, dst_type_id);
|
||||
|
||||
assert(src_storage_class == SpvStorageClassInput ||
|
||||
src_storage_class == SpvStorageClassOutput);
|
||||
assert(dst_storage_class == SpvStorageClassInput ||
|
||||
dst_storage_class == SpvStorageClassOutput);
|
||||
assert(src_storage_class == spv::StorageClass::Input ||
|
||||
src_storage_class == spv::StorageClass::Output);
|
||||
assert(dst_storage_class == spv::StorageClass::Input ||
|
||||
dst_storage_class == spv::StorageClass::Output);
|
||||
|
||||
return src_storage_class == dst_storage_class;
|
||||
}
|
||||
|
||||
bool Differ::MatchPerVertexVariable(const opt::Instruction* src_inst,
|
||||
const opt::Instruction* dst_inst) {
|
||||
SpvStorageClass src_storage_class =
|
||||
SpvStorageClass(src_inst->GetSingleWordInOperand(0));
|
||||
SpvStorageClass dst_storage_class =
|
||||
SpvStorageClass(dst_inst->GetSingleWordInOperand(0));
|
||||
spv::StorageClass src_storage_class =
|
||||
spv::StorageClass(src_inst->GetSingleWordInOperand(0));
|
||||
spv::StorageClass dst_storage_class =
|
||||
spv::StorageClass(dst_inst->GetSingleWordInOperand(0));
|
||||
|
||||
return src_storage_class == dst_storage_class;
|
||||
}
|
||||
@@ -1479,7 +1482,7 @@ InstructionList Differ::GetFunctionHeader(const opt::Function& function) {
|
||||
InstructionList body;
|
||||
function.WhileEachInst(
|
||||
[&body](const opt::Instruction* inst) {
|
||||
if (inst->opcode() == SpvOpLabel) {
|
||||
if (inst->opcode() == spv::Op::OpLabel) {
|
||||
return false;
|
||||
}
|
||||
body.push_back(inst);
|
||||
@@ -1694,12 +1697,12 @@ void Differ::MatchVariablesUsedByMatchedInstructions(
|
||||
default:
|
||||
// TODO: match functions based on OpFunctionCall?
|
||||
break;
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case SpvOpLoad:
|
||||
case SpvOpStore:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpLoad:
|
||||
case spv::Op::OpStore:
|
||||
const uint32_t src_pointer_id = src_inst->GetSingleWordInOperand(0);
|
||||
const uint32_t dst_pointer_id = dst_inst->GetSingleWordInOperand(0);
|
||||
if (IsVariable(src_id_to_, src_pointer_id) &&
|
||||
@@ -1727,23 +1730,24 @@ const opt::Instruction* Differ::GetInst(const IdInstructions& id_to,
|
||||
uint32_t Differ::GetConstantUint(const IdInstructions& id_to,
|
||||
uint32_t constant_id) {
|
||||
const opt::Instruction* constant_inst = GetInst(id_to, constant_id);
|
||||
assert(constant_inst->opcode() == SpvOpConstant);
|
||||
assert(GetInst(id_to, constant_inst->type_id())->opcode() == SpvOpTypeInt);
|
||||
assert(constant_inst->opcode() == spv::Op::OpConstant);
|
||||
assert(GetInst(id_to, constant_inst->type_id())->opcode() ==
|
||||
spv::Op::OpTypeInt);
|
||||
|
||||
return constant_inst->GetSingleWordInOperand(0);
|
||||
}
|
||||
|
||||
SpvExecutionModel Differ::GetExecutionModel(const opt::Module* module,
|
||||
uint32_t entry_point_id) {
|
||||
spv::ExecutionModel Differ::GetExecutionModel(const opt::Module* module,
|
||||
uint32_t entry_point_id) {
|
||||
for (const opt::Instruction& inst : module->entry_points()) {
|
||||
assert(inst.opcode() == SpvOpEntryPoint);
|
||||
assert(inst.opcode() == spv::Op::OpEntryPoint);
|
||||
if (inst.GetSingleWordOperand(1) == entry_point_id) {
|
||||
return SpvExecutionModel(inst.GetSingleWordOperand(0));
|
||||
return spv::ExecutionModel(inst.GetSingleWordOperand(0));
|
||||
}
|
||||
}
|
||||
|
||||
assert(false && "Unreachable");
|
||||
return SpvExecutionModel(0xFFF);
|
||||
return spv::ExecutionModel(0xFFF);
|
||||
}
|
||||
|
||||
bool Differ::HasName(const IdInstructions& id_to, uint32_t id) {
|
||||
@@ -1751,7 +1755,7 @@ bool Differ::HasName(const IdInstructions& id_to, uint32_t id) {
|
||||
assert(id < id_to.name_map_.size());
|
||||
|
||||
for (const opt::Instruction* inst : id_to.name_map_[id]) {
|
||||
if (inst->opcode() == SpvOpName) {
|
||||
if (inst->opcode() == spv::Op::OpName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1765,7 +1769,7 @@ std::string Differ::GetName(const IdInstructions& id_to, uint32_t id,
|
||||
assert(id < id_to.name_map_.size());
|
||||
|
||||
for (const opt::Instruction* inst : id_to.name_map_[id]) {
|
||||
if (inst->opcode() == SpvOpName) {
|
||||
if (inst->opcode() == spv::Op::OpName) {
|
||||
*has_name = true;
|
||||
return inst->GetOperand(1).AsString();
|
||||
}
|
||||
@@ -1788,11 +1792,11 @@ std::string Differ::GetSanitizedName(const IdInstructions& id_to, uint32_t id) {
|
||||
}
|
||||
|
||||
uint32_t Differ::GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
|
||||
SpvStorageClass* storage_class) {
|
||||
spv::StorageClass* storage_class) {
|
||||
const opt::Instruction* var_inst = GetInst(id_to, var_id);
|
||||
assert(var_inst->opcode() == SpvOpVariable);
|
||||
assert(var_inst->opcode() == spv::Op::OpVariable);
|
||||
|
||||
*storage_class = SpvStorageClass(var_inst->GetSingleWordInOperand(0));
|
||||
*storage_class = spv::StorageClass(var_inst->GetSingleWordInOperand(0));
|
||||
|
||||
// Get the type pointer from the variable.
|
||||
const uint32_t type_pointer_id = var_inst->type_id();
|
||||
@@ -1803,15 +1807,15 @@ uint32_t Differ::GetVarTypeId(const IdInstructions& id_to, uint32_t var_id,
|
||||
}
|
||||
|
||||
bool Differ::GetDecorationValue(const IdInstructions& id_to, uint32_t id,
|
||||
SpvDecoration decoration,
|
||||
spv::Decoration decoration,
|
||||
uint32_t* decoration_value) {
|
||||
assert(id != 0);
|
||||
assert(id < id_to.decoration_map_.size());
|
||||
|
||||
for (const opt::Instruction* inst : id_to.decoration_map_[id]) {
|
||||
if (inst->opcode() == SpvOpDecorate &&
|
||||
if (inst->opcode() == spv::Op::OpDecorate &&
|
||||
inst->GetSingleWordOperand(0) == id &&
|
||||
inst->GetSingleWordOperand(1) == decoration) {
|
||||
spv::Decoration(inst->GetSingleWordOperand(1)) == decoration) {
|
||||
*decoration_value = inst->GetSingleWordOperand(2);
|
||||
return true;
|
||||
}
|
||||
@@ -1828,28 +1832,28 @@ const opt::Instruction* Differ::GetForwardPointerInst(
|
||||
}
|
||||
|
||||
bool Differ::IsIntType(const IdInstructions& id_to, uint32_t type_id) {
|
||||
return IsOp(id_to, type_id, SpvOpTypeInt);
|
||||
return IsOp(id_to, type_id, spv::Op::OpTypeInt);
|
||||
}
|
||||
|
||||
bool Differ::IsFloatType(const IdInstructions& id_to, uint32_t type_id) {
|
||||
return IsOp(id_to, type_id, SpvOpTypeFloat);
|
||||
return IsOp(id_to, type_id, spv::Op::OpTypeFloat);
|
||||
}
|
||||
|
||||
bool Differ::IsConstantUint(const IdInstructions& id_to, uint32_t id) {
|
||||
const opt::Instruction* constant_inst = GetInst(id_to, id);
|
||||
if (constant_inst->opcode() != SpvOpConstant) {
|
||||
if (constant_inst->opcode() != spv::Op::OpConstant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const opt::Instruction* type_inst = GetInst(id_to, constant_inst->type_id());
|
||||
return type_inst->opcode() == SpvOpTypeInt;
|
||||
return type_inst->opcode() == spv::Op::OpTypeInt;
|
||||
}
|
||||
|
||||
bool Differ::IsVariable(const IdInstructions& id_to, uint32_t pointer_id) {
|
||||
return IsOp(id_to, pointer_id, SpvOpVariable);
|
||||
return IsOp(id_to, pointer_id, spv::Op::OpVariable);
|
||||
}
|
||||
|
||||
bool Differ::IsOp(const IdInstructions& id_to, uint32_t id, SpvOp op) {
|
||||
bool Differ::IsOp(const IdInstructions& id_to, uint32_t id, spv::Op op) {
|
||||
return GetInst(id_to, id)->opcode() == op;
|
||||
}
|
||||
|
||||
@@ -1858,17 +1862,18 @@ bool Differ::IsPerVertexType(const IdInstructions& id_to, uint32_t type_id) {
|
||||
assert(type_id < id_to.decoration_map_.size());
|
||||
|
||||
for (const opt::Instruction* inst : id_to.decoration_map_[type_id]) {
|
||||
if (inst->opcode() == SpvOpMemberDecorate &&
|
||||
if (inst->opcode() == spv::Op::OpMemberDecorate &&
|
||||
inst->GetSingleWordOperand(0) == type_id &&
|
||||
inst->GetSingleWordOperand(2) == SpvDecorationBuiltIn) {
|
||||
SpvBuiltIn built_in = SpvBuiltIn(inst->GetSingleWordOperand(3));
|
||||
spv::Decoration(inst->GetSingleWordOperand(2)) ==
|
||||
spv::Decoration::BuiltIn) {
|
||||
spv::BuiltIn built_in = spv::BuiltIn(inst->GetSingleWordOperand(3));
|
||||
|
||||
// Only gl_PerVertex can have, and it can only have, the following
|
||||
// built-in decorations.
|
||||
return built_in == SpvBuiltInPosition ||
|
||||
built_in == SpvBuiltInPointSize ||
|
||||
built_in == SpvBuiltInClipDistance ||
|
||||
built_in == SpvBuiltInCullDistance;
|
||||
return built_in == spv::BuiltIn::Position ||
|
||||
built_in == spv::BuiltIn::PointSize ||
|
||||
built_in == spv::BuiltIn::ClipDistance ||
|
||||
built_in == spv::BuiltIn::CullDistance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1877,12 +1882,12 @@ bool Differ::IsPerVertexType(const IdInstructions& id_to, uint32_t type_id) {
|
||||
|
||||
bool Differ::IsPerVertexVariable(const IdInstructions& id_to, uint32_t var_id) {
|
||||
// Get the type from the type pointer.
|
||||
SpvStorageClass storage_class;
|
||||
spv::StorageClass storage_class;
|
||||
uint32_t type_id = GetVarTypeId(id_to, var_id, &storage_class);
|
||||
const opt::Instruction* type_inst = GetInst(id_to, type_id);
|
||||
|
||||
// If array, get the element type.
|
||||
if (type_inst->opcode() == SpvOpTypeArray) {
|
||||
if (type_inst->opcode() == spv::Op::OpTypeArray) {
|
||||
type_id = type_inst->GetSingleWordInOperand(0);
|
||||
}
|
||||
|
||||
@@ -1890,21 +1895,21 @@ bool Differ::IsPerVertexVariable(const IdInstructions& id_to, uint32_t var_id) {
|
||||
return IsPerVertexType(id_to, type_id);
|
||||
}
|
||||
|
||||
SpvStorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
|
||||
uint32_t type_id) {
|
||||
spv::StorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
|
||||
uint32_t type_id) {
|
||||
for (const opt::Instruction& inst : module->types_values()) {
|
||||
switch (inst.opcode()) {
|
||||
case SpvOpTypeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
// The gl_PerVertex instance could be an array, look for a variable of
|
||||
// the array type instead.
|
||||
if (inst.GetSingleWordInOperand(0) == type_id) {
|
||||
type_id = inst.result_id();
|
||||
}
|
||||
break;
|
||||
case SpvOpTypePointer:
|
||||
case spv::Op::OpTypePointer:
|
||||
// Find the storage class of the pointer to this type.
|
||||
if (inst.GetSingleWordInOperand(1) == type_id) {
|
||||
return SpvStorageClass(inst.GetSingleWordInOperand(0));
|
||||
return spv::StorageClass(inst.GetSingleWordInOperand(0));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1915,7 +1920,7 @@ SpvStorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
|
||||
// gl_PerVertex is declared, but is unused. Return either of Input or Output
|
||||
// classes just so it matches one in the other module. This should be highly
|
||||
// unlikely, perhaps except for ancient GS-used-to-emulate-CS scenarios.
|
||||
return SpvStorageClassOutput;
|
||||
return spv::StorageClass::Output;
|
||||
}
|
||||
|
||||
spv_ext_inst_type_t Differ::GetExtInstType(const IdInstructions& id_to,
|
||||
@@ -1941,9 +1946,9 @@ spv_number_kind_t Differ::GetNumberKind(const IdInstructions& id_to,
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
|
||||
switch (inst.opcode()) {
|
||||
case SpvOpSwitch:
|
||||
case SpvOpConstant:
|
||||
case SpvOpSpecConstant:
|
||||
case spv::Op::OpSwitch:
|
||||
case spv::Op::OpConstant:
|
||||
case spv::Op::OpSpecConstant:
|
||||
// Same kind of number as the selector (OpSwitch) or the type
|
||||
// (Op*Constant).
|
||||
return GetTypeNumberKind(id_to, inst.GetSingleWordOperand(0),
|
||||
@@ -1969,12 +1974,12 @@ spv_number_kind_t Differ::GetTypeNumberKind(const IdInstructions& id_to,
|
||||
}
|
||||
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeInt:
|
||||
case spv::Op::OpTypeInt:
|
||||
*number_bit_width = type_inst->GetSingleWordOperand(1);
|
||||
return type_inst->GetSingleWordOperand(2) == 0 ? SPV_NUMBER_UNSIGNED_INT
|
||||
: SPV_NUMBER_SIGNED_INT;
|
||||
break;
|
||||
case SpvOpTypeFloat:
|
||||
case spv::Op::OpTypeFloat:
|
||||
*number_bit_width = type_inst->GetSingleWordOperand(1);
|
||||
return SPV_NUMBER_FLOATING;
|
||||
default:
|
||||
@@ -2092,7 +2097,7 @@ void Differ::MatchTypeForwardPointers() {
|
||||
return inst.GetSingleWordOperand(0);
|
||||
};
|
||||
auto accept_type_forward_pointer_ops = [](const opt::Instruction& inst) {
|
||||
return inst.opcode() == SpvOpTypeForwardPointer;
|
||||
return inst.opcode() == spv::Op::OpTypeForwardPointer;
|
||||
};
|
||||
|
||||
PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true,
|
||||
@@ -2116,17 +2121,17 @@ void Differ::MatchTypeForwardPointers() {
|
||||
// - If leftover is unique, match
|
||||
|
||||
// Group forwarded pointers by storage class first and loop over them.
|
||||
GroupIdsAndMatch<SpvStorageClass>(
|
||||
potential_id_map.src_ids, potential_id_map.dst_ids, SpvStorageClassMax,
|
||||
&Differ::GroupIdsHelperGetTypePointerStorageClass,
|
||||
GroupIdsAndMatch<spv::StorageClass>(
|
||||
potential_id_map.src_ids, potential_id_map.dst_ids,
|
||||
spv::StorageClass::Max, &Differ::GroupIdsHelperGetTypePointerStorageClass,
|
||||
[this](const IdGroup& src_group_by_storage_class,
|
||||
const IdGroup& dst_group_by_storage_class) {
|
||||
|
||||
// Group them further by the type they are pointing to and loop over
|
||||
// them.
|
||||
GroupIdsAndMatch<SpvOp>(
|
||||
src_group_by_storage_class, dst_group_by_storage_class, SpvOpMax,
|
||||
&Differ::GroupIdsHelperGetTypePointerTypeOp,
|
||||
GroupIdsAndMatch<spv::Op>(
|
||||
src_group_by_storage_class, dst_group_by_storage_class,
|
||||
spv::Op::Max, &Differ::GroupIdsHelperGetTypePointerTypeOp,
|
||||
[this](const IdGroup& src_group_by_type_op,
|
||||
const IdGroup& dst_group_by_type_op) {
|
||||
|
||||
@@ -2182,8 +2187,8 @@ void Differ::MatchTypeIds() {
|
||||
MatchIds(potential_id_map, [this, flexibility](
|
||||
const opt::Instruction* src_inst,
|
||||
const opt::Instruction* dst_inst) {
|
||||
const SpvOp src_op = src_inst->opcode();
|
||||
const SpvOp dst_op = dst_inst->opcode();
|
||||
const spv::Op src_op = src_inst->opcode();
|
||||
const spv::Op dst_op = dst_inst->opcode();
|
||||
|
||||
// Don't match if the opcode is not the same.
|
||||
if (src_op != dst_op) {
|
||||
@@ -2191,26 +2196,26 @@ void Differ::MatchTypeIds() {
|
||||
}
|
||||
|
||||
switch (src_op) {
|
||||
case SpvOpTypeVoid:
|
||||
case SpvOpTypeBool:
|
||||
case SpvOpTypeSampler:
|
||||
case spv::Op::OpTypeVoid:
|
||||
case spv::Op::OpTypeBool:
|
||||
case spv::Op::OpTypeSampler:
|
||||
// void, bool and sampler are unique, match them.
|
||||
return true;
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypePointer:
|
||||
case spv::Op::OpTypeInt:
|
||||
case spv::Op::OpTypeFloat:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
case spv::Op::OpTypeSampledImage:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypePointer:
|
||||
// Match these instructions when all operands match.
|
||||
assert(src_inst->NumInOperandWords() ==
|
||||
dst_inst->NumInOperandWords());
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0,
|
||||
src_inst->NumInOperandWords());
|
||||
|
||||
case SpvOpTypeFunction:
|
||||
case SpvOpTypeImage:
|
||||
case spv::Op::OpTypeFunction:
|
||||
case spv::Op::OpTypeImage:
|
||||
// Match function types only if they have the same number of operands,
|
||||
// and they all match.
|
||||
// Match image types similarly, expecting the optional final parameter
|
||||
@@ -2221,7 +2226,7 @@ void Differ::MatchTypeIds() {
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0,
|
||||
src_inst->NumInOperandWords());
|
||||
|
||||
case SpvOpTypeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
// Match arrays only if the element type and length match. The length
|
||||
// is an id of a constant, so the actual constant it's defining is
|
||||
// compared instead.
|
||||
@@ -2238,7 +2243,7 @@ void Differ::MatchTypeIds() {
|
||||
// example if a spec contant is used).
|
||||
return DoOperandsMatch(src_inst, dst_inst, 1, 1);
|
||||
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
return MatchOpTypeStruct(src_inst, dst_inst, flexibility);
|
||||
|
||||
default:
|
||||
@@ -2270,8 +2275,8 @@ void Differ::MatchConstants() {
|
||||
MatchIds(potential_id_map, [this, flexibility](
|
||||
const opt::Instruction* src_inst,
|
||||
const opt::Instruction* dst_inst) {
|
||||
const SpvOp src_op = src_inst->opcode();
|
||||
const SpvOp dst_op = dst_inst->opcode();
|
||||
const spv::Op src_op = src_inst->opcode();
|
||||
const spv::Op dst_op = dst_inst->opcode();
|
||||
|
||||
// Don't match if the opcode is not the same.
|
||||
if (src_op != dst_op) {
|
||||
@@ -2279,14 +2284,14 @@ void Differ::MatchConstants() {
|
||||
}
|
||||
|
||||
switch (src_op) {
|
||||
case SpvOpConstantTrue:
|
||||
case SpvOpConstantFalse:
|
||||
case spv::Op::OpConstantTrue:
|
||||
case spv::Op::OpConstantFalse:
|
||||
// true and false are unique, match them.
|
||||
return true;
|
||||
case SpvOpConstant:
|
||||
case spv::Op::OpConstant:
|
||||
return MatchOpConstant(src_inst, dst_inst, flexibility);
|
||||
case SpvOpConstantComposite:
|
||||
case SpvOpSpecConstantComposite:
|
||||
case spv::Op::OpConstantComposite:
|
||||
case spv::Op::OpSpecConstantComposite:
|
||||
// Composite constants must match in type and value.
|
||||
//
|
||||
// TODO: match OpConstantNull with OpConstantComposite with all zeros
|
||||
@@ -2299,7 +2304,7 @@ void Differ::MatchConstants() {
|
||||
dst_inst->GetOperand(0)) &&
|
||||
DoOperandsMatch(src_inst, dst_inst, 0,
|
||||
src_inst->NumInOperandWords());
|
||||
case SpvOpConstantSampler:
|
||||
case spv::Op::OpConstantSampler:
|
||||
// Match sampler constants exactly.
|
||||
// TODO: Allow flexibility in parameters to better diff shaders where
|
||||
// the sampler param has changed.
|
||||
@@ -2307,15 +2312,15 @@ void Differ::MatchConstants() {
|
||||
dst_inst->NumInOperandWords());
|
||||
return DoOperandsMatch(src_inst, dst_inst, 0,
|
||||
src_inst->NumInOperandWords());
|
||||
case SpvOpConstantNull:
|
||||
case spv::Op::OpConstantNull:
|
||||
// Match null constants as long as the type matches.
|
||||
return DoesOperandMatch(src_inst->GetOperand(0),
|
||||
dst_inst->GetOperand(0));
|
||||
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
case SpvOpSpecConstantOp:
|
||||
case spv::Op::OpSpecConstantTrue:
|
||||
case spv::Op::OpSpecConstantFalse:
|
||||
case spv::Op::OpSpecConstant:
|
||||
case spv::Op::OpSpecConstantOp:
|
||||
// Match spec constants by name if available, then by the SpecId
|
||||
// decoration.
|
||||
return MatchOpSpecConstant(src_inst, dst_inst);
|
||||
@@ -2334,7 +2339,7 @@ void Differ::MatchVariableIds() {
|
||||
return inst.result_id();
|
||||
};
|
||||
auto accept_type_ops = [](const opt::Instruction& inst) {
|
||||
return inst.opcode() == SpvOpVariable;
|
||||
return inst.opcode() == spv::Op::OpVariable;
|
||||
};
|
||||
|
||||
PoolPotentialIds(src_->types_values(), potential_id_map.src_ids, true,
|
||||
@@ -2350,8 +2355,8 @@ void Differ::MatchVariableIds() {
|
||||
MatchIds(potential_id_map,
|
||||
[this, flexibility](const opt::Instruction* src_inst,
|
||||
const opt::Instruction* dst_inst) {
|
||||
assert(src_inst->opcode() == SpvOpVariable);
|
||||
assert(dst_inst->opcode() == SpvOpVariable);
|
||||
assert(src_inst->opcode() == spv::Op::OpVariable);
|
||||
assert(dst_inst->opcode() == spv::Op::OpVariable);
|
||||
|
||||
return MatchOpVariable(src_inst, dst_inst, flexibility);
|
||||
});
|
||||
@@ -2597,7 +2602,7 @@ void Differ::ToParsedInstruction(
|
||||
parsed_inst->num_words = static_cast<uint16_t>(inst_binary.size());
|
||||
parsed_inst->opcode = static_cast<uint16_t>(inst.opcode());
|
||||
parsed_inst->ext_inst_type =
|
||||
inst.opcode() == SpvOpExtInst
|
||||
inst.opcode() == spv::Op::OpExtInst
|
||||
? GetExtInstType(id_to, original_inst.GetSingleWordInOperand(0))
|
||||
: SPV_EXT_INST_TYPE_NONE;
|
||||
parsed_inst->type_id =
|
||||
|
||||
10
3rdparty/spirv-tools/source/disassemble.cpp
vendored
10
3rdparty/spirv-tools/source/disassemble.cpp
vendored
@@ -244,7 +244,7 @@ void InstructionDisassembler::EmitHeaderSchema(uint32_t schema) {
|
||||
|
||||
void InstructionDisassembler::EmitInstruction(
|
||||
const spv_parsed_instruction_t& inst, size_t inst_byte_offset) {
|
||||
auto opcode = static_cast<SpvOp>(inst.opcode);
|
||||
auto opcode = static_cast<spv::Op>(inst.opcode);
|
||||
|
||||
if (inst.result_id) {
|
||||
SetBlue();
|
||||
@@ -268,7 +268,7 @@ void InstructionDisassembler::EmitInstruction(
|
||||
EmitOperand(inst, i);
|
||||
}
|
||||
|
||||
if (comment_ && opcode == SpvOpName) {
|
||||
if (comment_ && opcode == spv::Op::OpName) {
|
||||
const spv_parsed_operand_t& operand = inst.operands[0];
|
||||
const uint32_t word = inst.words[operand.offset];
|
||||
stream_ << " ; id %" << word;
|
||||
@@ -290,8 +290,8 @@ void InstructionDisassembler::EmitInstruction(
|
||||
void InstructionDisassembler::EmitSectionComment(
|
||||
const spv_parsed_instruction_t& inst, bool& inserted_decoration_space,
|
||||
bool& inserted_debug_space, bool& inserted_type_space) {
|
||||
auto opcode = static_cast<SpvOp>(inst.opcode);
|
||||
if (comment_ && opcode == SpvOpFunction) {
|
||||
auto opcode = static_cast<spv::Op>(inst.opcode);
|
||||
if (comment_ && opcode == spv::Op::OpFunction) {
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl;
|
||||
@@ -351,7 +351,7 @@ void InstructionDisassembler::EmitOperand(const spv_parsed_instruction_t& inst,
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (grammar_.lookupOpcode(SpvOp(word), &opcode_desc))
|
||||
if (grammar_.lookupOpcode(spv::Op(word), &opcode_desc))
|
||||
assert(false && "should have caught this earlier");
|
||||
SetRed();
|
||||
stream_ << opcode_desc->name;
|
||||
|
||||
4
3rdparty/spirv-tools/source/enum_set.h
vendored
4
3rdparty/spirv-tools/source/enum_set.h
vendored
@@ -200,8 +200,8 @@ class EnumSet {
|
||||
std::unique_ptr<OverflowSetType> overflow_ = {};
|
||||
};
|
||||
|
||||
// A set of SpvCapability, optimized for small capability values.
|
||||
using CapabilitySet = EnumSet<SpvCapability>;
|
||||
// A set of spv::Capability, optimized for small capability values.
|
||||
using CapabilitySet = EnumSet<spv::Capability>;
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ bool GetExtensionFromString(const char* str, Extension* extension);
|
||||
const char* ExtensionToString(Extension extension);
|
||||
|
||||
// Returns text string corresponding to |capability|.
|
||||
const char* CapabilityToString(SpvCapability capability);
|
||||
const char* CapabilityToString(spv::Capability capability);
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
|
||||
4
3rdparty/spirv-tools/source/extensions.cpp
vendored
4
3rdparty/spirv-tools/source/extensions.cpp
vendored
@@ -24,7 +24,9 @@
|
||||
namespace spvtools {
|
||||
|
||||
std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
|
||||
if (inst->opcode != SpvOpExtension) return "ERROR_not_op_extension";
|
||||
if (inst->opcode != static_cast<uint16_t>(spv::Op::OpExtension)) {
|
||||
return "ERROR_not_op_extension";
|
||||
}
|
||||
|
||||
assert(inst->num_operands == 1);
|
||||
|
||||
|
||||
2
3rdparty/spirv-tools/source/instruction.h
vendored
2
3rdparty/spirv-tools/source/instruction.h
vendored
@@ -26,7 +26,7 @@ struct spv_instruction_t {
|
||||
// Normally, both opcode and extInstType contain valid data.
|
||||
// However, when the assembler parses !<number> as the first word in
|
||||
// an instruction and opcode and extInstType are invalid.
|
||||
SpvOp opcode;
|
||||
spv::Op opcode;
|
||||
spv_ext_inst_type_t extInstType;
|
||||
|
||||
// The Id of the result type, if this instruction has one. Zero otherwise.
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
#ifndef SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
|
||||
#define SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
|
||||
|
||||
#include "spirv/unified1/spirv.h"
|
||||
#include "spirv/unified1/spirv.hpp11"
|
||||
|
||||
#endif // SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
|
||||
|
||||
57
3rdparty/spirv-tools/source/link/linker.cpp
vendored
57
3rdparty/spirv-tools/source/link/linker.cpp
vendored
@@ -57,12 +57,12 @@ using opt::analysis::TypeManager;
|
||||
|
||||
// Stores various information about an imported or exported symbol.
|
||||
struct LinkageSymbolInfo {
|
||||
SpvId id; // ID of the symbol
|
||||
SpvId type_id; // ID of the type of the symbol
|
||||
spv::Id id; // ID of the symbol
|
||||
spv::Id type_id; // ID of the type of the symbol
|
||||
std::string name; // unique name defining the symbol and used for matching
|
||||
// imports and exports together
|
||||
std::vector<SpvId> parameter_ids; // ID of the parameters of the symbol, if
|
||||
// it is a function
|
||||
std::vector<spv::Id> parameter_ids; // ID of the parameters of the symbol, if
|
||||
// it is a function
|
||||
};
|
||||
struct LinkageEntry {
|
||||
LinkageSymbolInfo imported_symbol;
|
||||
@@ -226,7 +226,7 @@ spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
<< " (input module " << (i + 1) << ").";
|
||||
}
|
||||
|
||||
header->magic_number = SpvMagicNumber;
|
||||
header->magic_number = spv::MagicNumber;
|
||||
header->version = linked_version;
|
||||
header->generator = SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_LINKER, 0);
|
||||
header->bound = max_id_bound;
|
||||
@@ -367,7 +367,7 @@ spv_result_t MergeModules(const MessageConsumer& consumer,
|
||||
std::vector<uint32_t> processed_words =
|
||||
spvtools::utils::MakeVector(processed_string);
|
||||
linked_module->AddDebug3Inst(std::unique_ptr<Instruction>(
|
||||
new Instruction(linked_context, SpvOpModuleProcessed, 0u, 0u,
|
||||
new Instruction(linked_context, spv::Op::OpModuleProcessed, 0u, 0u,
|
||||
{{SPV_OPERAND_TYPE_LITERAL_STRING, processed_words}})));
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ spv_result_t MergeModules(const MessageConsumer& consumer,
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
// TODO(pierremoreau): Since the modules have not been validate, should we
|
||||
// expect SpvStorageClassFunction variables outside
|
||||
// expect spv::StorageClass::Function variables outside
|
||||
// functions?
|
||||
for (const auto& module : input_modules) {
|
||||
for (const auto& inst : module->types_values()) {
|
||||
@@ -414,16 +414,18 @@ spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
|
||||
|
||||
// Figure out the imports and exports
|
||||
for (const auto& decoration : linked_context.annotations()) {
|
||||
if (decoration.opcode() != SpvOpDecorate ||
|
||||
decoration.GetSingleWordInOperand(1u) != SpvDecorationLinkageAttributes)
|
||||
if (decoration.opcode() != spv::Op::OpDecorate ||
|
||||
spv::Decoration(decoration.GetSingleWordInOperand(1u)) !=
|
||||
spv::Decoration::LinkageAttributes)
|
||||
continue;
|
||||
|
||||
const SpvId id = decoration.GetSingleWordInOperand(0u);
|
||||
const spv::Id id = decoration.GetSingleWordInOperand(0u);
|
||||
// Ignore if the targeted symbol is a built-in
|
||||
bool is_built_in = false;
|
||||
for (const auto& id_decoration :
|
||||
decoration_manager.GetDecorationsFor(id, false)) {
|
||||
if (id_decoration->GetSingleWordInOperand(1u) == SpvDecorationBuiltIn) {
|
||||
if (spv::Decoration(id_decoration->GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::BuiltIn) {
|
||||
is_built_in = true;
|
||||
break;
|
||||
}
|
||||
@@ -447,9 +449,9 @@ spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
|
||||
return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
|
||||
<< "ID " << id << " is never defined:\n";
|
||||
|
||||
if (def_inst->opcode() == SpvOpVariable) {
|
||||
if (def_inst->opcode() == spv::Op::OpVariable) {
|
||||
symbol_info.type_id = def_inst->type_id();
|
||||
} else if (def_inst->opcode() == SpvOpFunction) {
|
||||
} else if (def_inst->opcode() == spv::Op::OpFunction) {
|
||||
symbol_info.type_id = def_inst->GetSingleWordInOperand(1u);
|
||||
|
||||
// range-based for loop calls begin()/end(), but never cbegin()/cend(),
|
||||
@@ -467,9 +469,9 @@ spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
|
||||
<< " LinkageAttributes; " << id << " is neither of them.\n";
|
||||
}
|
||||
|
||||
if (type == SpvLinkageTypeImport)
|
||||
if (spv::LinkageType(type) == spv::LinkageType::Import)
|
||||
imports.push_back(symbol_info);
|
||||
else if (type == SpvLinkageTypeExport)
|
||||
else if (spv::LinkageType(type) == spv::LinkageType::Export)
|
||||
exports[symbol_info.name].push_back(symbol_info);
|
||||
}
|
||||
|
||||
@@ -585,7 +587,7 @@ spv_result_t RemoveLinkageSpecificInstructions(
|
||||
// TODO(pierremoreau): This will not work if the decoration is applied
|
||||
// through a group, but the linker does not support that
|
||||
// either.
|
||||
std::unordered_set<SpvId> imports;
|
||||
std::unordered_set<spv::Id> imports;
|
||||
if (options.GetAllowPartialLinkage()) {
|
||||
imports.reserve(linkings_to_do.size());
|
||||
for (const auto& linking_entry : linkings_to_do)
|
||||
@@ -601,9 +603,11 @@ spv_result_t RemoveLinkageSpecificInstructions(
|
||||
// * if we do not allow partial linkage, remove all import annotations;
|
||||
// * otherwise, remove the annotation only if there was a corresponding
|
||||
// export.
|
||||
if (inst->opcode() == SpvOpDecorate &&
|
||||
inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
|
||||
inst->GetSingleWordOperand(3u) == SpvLinkageTypeImport &&
|
||||
if (inst->opcode() == spv::Op::OpDecorate &&
|
||||
spv::Decoration(inst->GetSingleWordOperand(1u)) ==
|
||||
spv::Decoration::LinkageAttributes &&
|
||||
spv::LinkageType(inst->GetSingleWordOperand(3u)) ==
|
||||
spv::LinkageType::Import &&
|
||||
(!options.GetAllowPartialLinkage() ||
|
||||
imports.find(inst->GetSingleWordOperand(0u)) != imports.end())) {
|
||||
linked_context->KillInst(&*inst);
|
||||
@@ -616,9 +620,11 @@ spv_result_t RemoveLinkageSpecificInstructions(
|
||||
for (auto inst = next; inst != linked_context->annotation_end();
|
||||
inst = next) {
|
||||
++next;
|
||||
if (inst->opcode() == SpvOpDecorate &&
|
||||
inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
|
||||
inst->GetSingleWordOperand(3u) == SpvLinkageTypeExport) {
|
||||
if (inst->opcode() == spv::Op::OpDecorate &&
|
||||
spv::Decoration(inst->GetSingleWordOperand(1u)) ==
|
||||
spv::Decoration::LinkageAttributes &&
|
||||
spv::LinkageType(inst->GetSingleWordOperand(3u)) ==
|
||||
spv::LinkageType::Export) {
|
||||
linked_context->KillInst(&*inst);
|
||||
}
|
||||
}
|
||||
@@ -628,10 +634,11 @@ spv_result_t RemoveLinkageSpecificInstructions(
|
||||
// not allowed
|
||||
if (!options.GetCreateLibrary() && !options.GetAllowPartialLinkage()) {
|
||||
for (auto& inst : linked_context->capabilities())
|
||||
if (inst.GetSingleWordInOperand(0u) == SpvCapabilityLinkage) {
|
||||
if (spv::Capability(inst.GetSingleWordInOperand(0u)) ==
|
||||
spv::Capability::Linkage) {
|
||||
linked_context->KillInst(&inst);
|
||||
// The RemoveDuplicatesPass did remove duplicated capabilities, so we
|
||||
// now there aren’t more SpvCapabilityLinkage further down.
|
||||
// now there aren’t more spv::Capability::Linkage further down.
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -671,7 +678,7 @@ spv_result_t VerifyLimits(const MessageConsumer& consumer,
|
||||
|
||||
size_t num_global_values = 0u;
|
||||
for (const auto& inst : linked_context.module()->types_values()) {
|
||||
num_global_values += inst.opcode() == SpvOpVariable;
|
||||
num_global_values += inst.opcode() == spv::Op::OpVariable;
|
||||
}
|
||||
if (num_global_values >= SPV_LIMIT_GLOBAL_VARIABLES_MAX)
|
||||
DiagnosticStream(position, consumer, "", SPV_WARNING)
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "source/opt/dataflow.h"
|
||||
#include "source/opt/function.h"
|
||||
#include "source/opt/instruction.h"
|
||||
#include "spirv/unified1/spirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace lint {
|
||||
@@ -32,7 +31,7 @@ void DivergenceAnalysis::EnqueueSuccessors(opt::Instruction* inst) {
|
||||
uint32_t block_id;
|
||||
if (inst->IsBlockTerminator()) {
|
||||
block_id = context().get_instr_block(inst)->id();
|
||||
} else if (inst->opcode() == SpvOpLabel) {
|
||||
} else if (inst->opcode() == spv::Op::OpLabel) {
|
||||
block_id = inst->result_id();
|
||||
opt::BasicBlock* bb = context().cfg()->block(block_id);
|
||||
// Only enqueue phi instructions, as other uses don't affect divergence.
|
||||
@@ -54,7 +53,7 @@ void DivergenceAnalysis::EnqueueSuccessors(opt::Instruction* inst) {
|
||||
|
||||
opt::DataFlowAnalysis::VisitResult DivergenceAnalysis::Visit(
|
||||
opt::Instruction* inst) {
|
||||
if (inst->opcode() == SpvOpLabel) {
|
||||
if (inst->opcode() == spv::Op::OpLabel) {
|
||||
return VisitBlock(inst->result_id());
|
||||
} else {
|
||||
return VisitInstruction(inst);
|
||||
@@ -128,12 +127,12 @@ DivergenceAnalysis::ComputeInstructionDivergence(opt::Instruction* inst) {
|
||||
// Device/QueueFamily could satisfy fully uniform.
|
||||
uint32_t id = inst->result_id();
|
||||
// Handle divergence roots.
|
||||
if (inst->opcode() == SpvOpFunctionParameter) {
|
||||
if (inst->opcode() == spv::Op::OpFunctionParameter) {
|
||||
divergence_source_[id] = 0;
|
||||
return divergence_[id] = DivergenceLevel::kDivergent;
|
||||
} else if (inst->IsLoad()) {
|
||||
spvtools::opt::Instruction* var = inst->GetBaseAddress();
|
||||
if (var->opcode() != SpvOpVariable) {
|
||||
if (var->opcode() != spv::Op::OpVariable) {
|
||||
// Assume divergent.
|
||||
divergence_source_[id] = 0;
|
||||
return DivergenceLevel::kDivergent;
|
||||
@@ -166,29 +165,30 @@ DivergenceAnalysis::ComputeVariableDivergence(opt::Instruction* var) {
|
||||
uint32_t def_id = var->result_id();
|
||||
DivergenceLevel ret;
|
||||
switch (type->storage_class()) {
|
||||
case SpvStorageClassFunction:
|
||||
case SpvStorageClassGeneric:
|
||||
case SpvStorageClassAtomicCounter:
|
||||
case SpvStorageClassStorageBuffer:
|
||||
case SpvStorageClassPhysicalStorageBuffer:
|
||||
case SpvStorageClassOutput:
|
||||
case SpvStorageClassWorkgroup:
|
||||
case SpvStorageClassImage: // Image atomics probably aren't uniform.
|
||||
case SpvStorageClassPrivate:
|
||||
case spv::StorageClass::Function:
|
||||
case spv::StorageClass::Generic:
|
||||
case spv::StorageClass::AtomicCounter:
|
||||
case spv::StorageClass::StorageBuffer:
|
||||
case spv::StorageClass::PhysicalStorageBuffer:
|
||||
case spv::StorageClass::Output:
|
||||
case spv::StorageClass::Workgroup:
|
||||
case spv::StorageClass::Image: // Image atomics probably aren't uniform.
|
||||
case spv::StorageClass::Private:
|
||||
ret = DivergenceLevel::kDivergent;
|
||||
break;
|
||||
case SpvStorageClassInput:
|
||||
case spv::StorageClass::Input:
|
||||
ret = DivergenceLevel::kDivergent;
|
||||
// If this variable has a Flat decoration, it is partially uniform.
|
||||
// TODO(kuhar): Track access chain indices and also consider Flat members
|
||||
// of a structure.
|
||||
context().get_decoration_mgr()->WhileEachDecoration(
|
||||
def_id, SpvDecorationFlat, [&ret](const opt::Instruction&) {
|
||||
def_id, static_cast<uint32_t>(spv::Decoration::Flat),
|
||||
[&ret](const opt::Instruction&) {
|
||||
ret = DivergenceLevel::kPartiallyUniform;
|
||||
return false;
|
||||
});
|
||||
break;
|
||||
case SpvStorageClassUniformConstant:
|
||||
case spv::StorageClass::UniformConstant:
|
||||
// May be a storage image which is also written to; mark those as
|
||||
// divergent.
|
||||
if (!var->IsVulkanStorageImage() || var->IsReadOnlyPointer()) {
|
||||
@@ -197,9 +197,10 @@ DivergenceAnalysis::ComputeVariableDivergence(opt::Instruction* var) {
|
||||
ret = DivergenceLevel::kDivergent;
|
||||
}
|
||||
break;
|
||||
case SpvStorageClassUniform:
|
||||
case SpvStorageClassPushConstant:
|
||||
case SpvStorageClassCrossWorkgroup: // Not for shaders; default uniform.
|
||||
case spv::StorageClass::Uniform:
|
||||
case spv::StorageClass::PushConstant:
|
||||
case spv::StorageClass::CrossWorkgroup: // Not for shaders; default
|
||||
// uniform.
|
||||
default:
|
||||
ret = DivergenceLevel::kUniform;
|
||||
break;
|
||||
@@ -216,7 +217,7 @@ void DivergenceAnalysis::Setup(opt::Function* function) {
|
||||
function->entry().get(), [this](const opt::BasicBlock* bb) {
|
||||
uint32_t id = bb->id();
|
||||
if (bb->terminator() == nullptr ||
|
||||
bb->terminator()->opcode() != SpvOpBranch) {
|
||||
bb->terminator()->opcode() != spv::Op::OpBranch) {
|
||||
follow_unconditional_branches_[id] = id;
|
||||
} else {
|
||||
uint32_t target_id = bb->terminator()->GetSingleWordInOperand(0);
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/unified1/spirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace lint {
|
||||
@@ -43,7 +42,7 @@ std::string GetFriendlyName(opt::IRContext* context, uint32_t id) {
|
||||
ss << id;
|
||||
} else {
|
||||
opt::Instruction* inst_name = names.begin()->second;
|
||||
if (inst_name->opcode() == SpvOpName) {
|
||||
if (inst_name->opcode() == spv::Op::OpName) {
|
||||
ss << names.begin()->second->GetInOperand(0).AsString();
|
||||
ss << "[" << id << "]";
|
||||
} else {
|
||||
@@ -54,26 +53,26 @@ std::string GetFriendlyName(opt::IRContext* context, uint32_t id) {
|
||||
}
|
||||
|
||||
bool InstructionHasDerivative(const opt::Instruction& inst) {
|
||||
static const SpvOp derivative_opcodes[] = {
|
||||
static const spv::Op derivative_opcodes[] = {
|
||||
// Implicit derivatives.
|
||||
SpvOpImageSampleImplicitLod,
|
||||
SpvOpImageSampleDrefImplicitLod,
|
||||
SpvOpImageSampleProjImplicitLod,
|
||||
SpvOpImageSampleProjDrefImplicitLod,
|
||||
SpvOpImageSparseSampleImplicitLod,
|
||||
SpvOpImageSparseSampleDrefImplicitLod,
|
||||
SpvOpImageSparseSampleProjImplicitLod,
|
||||
SpvOpImageSparseSampleProjDrefImplicitLod,
|
||||
spv::Op::OpImageSampleImplicitLod,
|
||||
spv::Op::OpImageSampleDrefImplicitLod,
|
||||
spv::Op::OpImageSampleProjImplicitLod,
|
||||
spv::Op::OpImageSampleProjDrefImplicitLod,
|
||||
spv::Op::OpImageSparseSampleImplicitLod,
|
||||
spv::Op::OpImageSparseSampleDrefImplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjImplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjDrefImplicitLod,
|
||||
// Explicit derivatives.
|
||||
SpvOpDPdx,
|
||||
SpvOpDPdy,
|
||||
SpvOpFwidth,
|
||||
SpvOpDPdxFine,
|
||||
SpvOpDPdyFine,
|
||||
SpvOpFwidthFine,
|
||||
SpvOpDPdxCoarse,
|
||||
SpvOpDPdyCoarse,
|
||||
SpvOpFwidthCoarse,
|
||||
spv::Op::OpDPdx,
|
||||
spv::Op::OpDPdy,
|
||||
spv::Op::OpFwidth,
|
||||
spv::Op::OpDPdxFine,
|
||||
spv::Op::OpDPdyFine,
|
||||
spv::Op::OpFwidthFine,
|
||||
spv::Op::OpDPdxCoarse,
|
||||
spv::Op::OpDPdyCoarse,
|
||||
spv::Op::OpFwidthCoarse,
|
||||
};
|
||||
return std::find(std::begin(derivative_opcodes), std::end(derivative_opcodes),
|
||||
inst.opcode()) != std::end(derivative_opcodes);
|
||||
@@ -97,13 +96,14 @@ void PrintDivergenceFlow(opt::IRContext* context, DivergenceAnalysis div,
|
||||
opt::analysis::DefUseManager* def_use = context->get_def_use_mgr();
|
||||
opt::CFG* cfg = context->cfg();
|
||||
while (id != 0) {
|
||||
bool is_block = def_use->GetDef(id)->opcode() == SpvOpLabel;
|
||||
bool is_block = def_use->GetDef(id)->opcode() == spv::Op::OpLabel;
|
||||
if (is_block) {
|
||||
Warn(context, nullptr)
|
||||
<< "block " << GetFriendlyName(context, id) << " is divergent";
|
||||
uint32_t source = div.GetDivergenceSource(id);
|
||||
// Skip intermediate blocks.
|
||||
while (source != 0 && def_use->GetDef(source)->opcode() == SpvOpLabel) {
|
||||
while (source != 0 &&
|
||||
def_use->GetDef(source)->opcode() == spv::Op::OpLabel) {
|
||||
id = source;
|
||||
source = div.GetDivergenceSource(id);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ void PrintDivergenceFlow(opt::IRContext* context, DivergenceAnalysis div,
|
||||
opt::Instruction* source_def =
|
||||
source == 0 ? nullptr : def_use->GetDef(source);
|
||||
// First print data -> data dependencies.
|
||||
while (source != 0 && source_def->opcode() != SpvOpLabel) {
|
||||
while (source != 0 && source_def->opcode() != spv::Op::OpLabel) {
|
||||
Warn(context, def_use->GetDef(id))
|
||||
<< "because " << GetFriendlyName(context, id) << " uses value "
|
||||
<< GetFriendlyName(context, source)
|
||||
|
||||
1
3rdparty/spirv-tools/source/lint/linter.cpp
vendored
1
3rdparty/spirv-tools/source/lint/linter.cpp
vendored
@@ -19,7 +19,6 @@
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "spirv/unified1/spirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
|
||||
58
3rdparty/spirv-tools/source/name_mapper.cpp
vendored
58
3rdparty/spirv-tools/source/name_mapper.cpp
vendored
@@ -100,18 +100,18 @@ void FriendlyNameMapper::SaveName(uint32_t id,
|
||||
void FriendlyNameMapper::SaveBuiltInName(uint32_t target_id,
|
||||
uint32_t built_in) {
|
||||
#define GLCASE(name) \
|
||||
case SpvBuiltIn##name: \
|
||||
case spv::BuiltIn::name: \
|
||||
SaveName(target_id, "gl_" #name); \
|
||||
return;
|
||||
#define GLCASE2(name, suggested) \
|
||||
case SpvBuiltIn##name: \
|
||||
case spv::BuiltIn::name: \
|
||||
SaveName(target_id, "gl_" #suggested); \
|
||||
return;
|
||||
#define CASE(name) \
|
||||
case SpvBuiltIn##name: \
|
||||
case spv::BuiltIn::name: \
|
||||
SaveName(target_id, #name); \
|
||||
return;
|
||||
switch (built_in) {
|
||||
switch (spv::BuiltIn(built_in)) {
|
||||
GLCASE(Position)
|
||||
GLCASE(PointSize)
|
||||
GLCASE(ClipDistance)
|
||||
@@ -170,28 +170,28 @@ void FriendlyNameMapper::SaveBuiltInName(uint32_t target_id,
|
||||
spv_result_t FriendlyNameMapper::ParseInstruction(
|
||||
const spv_parsed_instruction_t& inst) {
|
||||
const auto result_id = inst.result_id;
|
||||
switch (inst.opcode) {
|
||||
case SpvOpName:
|
||||
switch (spv::Op(inst.opcode)) {
|
||||
case spv::Op::OpName:
|
||||
SaveName(inst.words[1], spvDecodeLiteralStringOperand(inst, 1));
|
||||
break;
|
||||
case SpvOpDecorate:
|
||||
case spv::Op::OpDecorate:
|
||||
// Decorations come after OpName. So OpName will take precedence over
|
||||
// decorations.
|
||||
//
|
||||
// In theory, we should also handle OpGroupDecorate. But that's unlikely
|
||||
// to occur.
|
||||
if (inst.words[2] == SpvDecorationBuiltIn) {
|
||||
if (spv::Decoration(inst.words[2]) == spv::Decoration::BuiltIn) {
|
||||
assert(inst.num_words > 3);
|
||||
SaveBuiltInName(inst.words[1], inst.words[3]);
|
||||
}
|
||||
break;
|
||||
case SpvOpTypeVoid:
|
||||
case spv::Op::OpTypeVoid:
|
||||
SaveName(result_id, "void");
|
||||
break;
|
||||
case SpvOpTypeBool:
|
||||
case spv::Op::OpTypeBool:
|
||||
SaveName(result_id, "bool");
|
||||
break;
|
||||
case SpvOpTypeInt: {
|
||||
case spv::Op::OpTypeInt: {
|
||||
std::string signedness;
|
||||
std::string root;
|
||||
const auto bit_width = inst.words[2];
|
||||
@@ -216,7 +216,7 @@ spv_result_t FriendlyNameMapper::ParseInstruction(
|
||||
if (0 == inst.words[3]) signedness = "u";
|
||||
SaveName(result_id, signedness + root);
|
||||
} break;
|
||||
case SpvOpTypeFloat: {
|
||||
case spv::Op::OpTypeFloat: {
|
||||
const auto bit_width = inst.words[2];
|
||||
switch (bit_width) {
|
||||
case 16:
|
||||
@@ -233,68 +233,68 @@ spv_result_t FriendlyNameMapper::ParseInstruction(
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case SpvOpTypeVector:
|
||||
case spv::Op::OpTypeVector:
|
||||
SaveName(result_id, std::string("v") + to_string(inst.words[3]) +
|
||||
NameForId(inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
SaveName(result_id, std::string("mat") + to_string(inst.words[3]) +
|
||||
NameForId(inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
SaveName(result_id, std::string("_arr_") + NameForId(inst.words[2]) +
|
||||
"_" + NameForId(inst.words[3]));
|
||||
break;
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
SaveName(result_id,
|
||||
std::string("_runtimearr_") + NameForId(inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypePointer:
|
||||
case spv::Op::OpTypePointer:
|
||||
SaveName(result_id, std::string("_ptr_") +
|
||||
NameForEnumOperand(SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
inst.words[2]) +
|
||||
"_" + NameForId(inst.words[3]));
|
||||
break;
|
||||
case SpvOpTypePipe:
|
||||
case spv::Op::OpTypePipe:
|
||||
SaveName(result_id,
|
||||
std::string("Pipe") +
|
||||
NameForEnumOperand(SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
|
||||
inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypeEvent:
|
||||
case spv::Op::OpTypeEvent:
|
||||
SaveName(result_id, "Event");
|
||||
break;
|
||||
case SpvOpTypeDeviceEvent:
|
||||
case spv::Op::OpTypeDeviceEvent:
|
||||
SaveName(result_id, "DeviceEvent");
|
||||
break;
|
||||
case SpvOpTypeReserveId:
|
||||
case spv::Op::OpTypeReserveId:
|
||||
SaveName(result_id, "ReserveId");
|
||||
break;
|
||||
case SpvOpTypeQueue:
|
||||
case spv::Op::OpTypeQueue:
|
||||
SaveName(result_id, "Queue");
|
||||
break;
|
||||
case SpvOpTypeOpaque:
|
||||
case spv::Op::OpTypeOpaque:
|
||||
SaveName(result_id, std::string("Opaque_") +
|
||||
Sanitize(spvDecodeLiteralStringOperand(inst, 1)));
|
||||
break;
|
||||
case SpvOpTypePipeStorage:
|
||||
case spv::Op::OpTypePipeStorage:
|
||||
SaveName(result_id, "PipeStorage");
|
||||
break;
|
||||
case SpvOpTypeNamedBarrier:
|
||||
case spv::Op::OpTypeNamedBarrier:
|
||||
SaveName(result_id, "NamedBarrier");
|
||||
break;
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
// Structs are mapped rather simplisitically. Just indicate that they
|
||||
// are a struct and then give the raw Id number.
|
||||
SaveName(result_id, std::string("_struct_") + to_string(result_id));
|
||||
break;
|
||||
case SpvOpConstantTrue:
|
||||
case spv::Op::OpConstantTrue:
|
||||
SaveName(result_id, "true");
|
||||
break;
|
||||
case SpvOpConstantFalse:
|
||||
case spv::Op::OpConstantFalse:
|
||||
SaveName(result_id, "false");
|
||||
break;
|
||||
case SpvOpConstant: {
|
||||
case spv::Op::OpConstant: {
|
||||
std::ostringstream value;
|
||||
EmitNumericLiteral(&value, inst, inst.operands[2]);
|
||||
auto value_str = value.str();
|
||||
|
||||
770
3rdparty/spirv-tools/source/opcode.cpp
vendored
770
3rdparty/spirv-tools/source/opcode.cpp
vendored
@@ -64,7 +64,7 @@ const char* spvGeneratorStr(uint32_t generator) {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
|
||||
uint32_t spvOpcodeMake(uint16_t wordCount, spv::Op opcode) {
|
||||
return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ spv_result_t spvOpcodeTableNameLookup(spv_target_env env,
|
||||
|
||||
spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
|
||||
const spv_opcode_table table,
|
||||
const SpvOp opcode,
|
||||
const spv::Op opcode,
|
||||
spv_opcode_desc* pEntry) {
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
if (!pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
@@ -166,7 +166,7 @@ spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
|
||||
const uint16_t wordCount, const spv_endianness_t endian,
|
||||
spv_instruction_t* pInst) {
|
||||
pInst->opcode = opcode;
|
||||
@@ -177,7 +177,7 @@ void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
uint16_t thisWordCount;
|
||||
uint16_t thisOpcode;
|
||||
spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
|
||||
assert(opcode == static_cast<SpvOp>(thisOpcode) &&
|
||||
assert(opcode == static_cast<spv::Op>(thisOpcode) &&
|
||||
wordCount == thisWordCount && "Endianness failed!");
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,7 @@ void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
const char* spvOpcodeString(const uint32_t opcode) {
|
||||
const auto beg = kOpcodeTableEntries;
|
||||
const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries);
|
||||
spv_opcode_desc_t needle = {"", static_cast<SpvOp>(opcode),
|
||||
spv_opcode_desc_t needle = {"", static_cast<spv::Op>(opcode),
|
||||
0, nullptr,
|
||||
0, {},
|
||||
false, false,
|
||||
@@ -196,7 +196,7 @@ const char* spvOpcodeString(const uint32_t opcode) {
|
||||
return lhs.opcode < rhs.opcode;
|
||||
};
|
||||
auto it = std::lower_bound(beg, end, needle, comp);
|
||||
if (it != end && it->opcode == opcode) {
|
||||
if (it != end && it->opcode == spv::Op(opcode)) {
|
||||
return it->name;
|
||||
}
|
||||
|
||||
@@ -204,140 +204,145 @@ const char* spvOpcodeString(const uint32_t opcode) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
|
||||
const char* spvOpcodeString(const spv::Op opcode) {
|
||||
return spvOpcodeString(static_cast<uint32_t>(opcode));
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsScalarType(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeBool:
|
||||
case spv::Op::OpTypeInt:
|
||||
case spv::Op::OpTypeFloat:
|
||||
case spv::Op::OpTypeBool:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsSpecConstant(const SpvOp opcode) {
|
||||
int32_t spvOpcodeIsSpecConstant(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
case SpvOpSpecConstantComposite:
|
||||
case SpvOpSpecConstantOp:
|
||||
case spv::Op::OpSpecConstantTrue:
|
||||
case spv::Op::OpSpecConstantFalse:
|
||||
case spv::Op::OpSpecConstant:
|
||||
case spv::Op::OpSpecConstantComposite:
|
||||
case spv::Op::OpSpecConstantOp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsConstant(const SpvOp opcode) {
|
||||
int32_t spvOpcodeIsConstant(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpConstantTrue:
|
||||
case SpvOpConstantFalse:
|
||||
case SpvOpConstant:
|
||||
case SpvOpConstantComposite:
|
||||
case SpvOpConstantSampler:
|
||||
case SpvOpConstantNull:
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
case SpvOpSpecConstantComposite:
|
||||
case SpvOpSpecConstantOp:
|
||||
case spv::Op::OpConstantTrue:
|
||||
case spv::Op::OpConstantFalse:
|
||||
case spv::Op::OpConstant:
|
||||
case spv::Op::OpConstantComposite:
|
||||
case spv::Op::OpConstantSampler:
|
||||
case spv::Op::OpConstantNull:
|
||||
case spv::Op::OpSpecConstantTrue:
|
||||
case spv::Op::OpSpecConstantFalse:
|
||||
case spv::Op::OpSpecConstant:
|
||||
case spv::Op::OpSpecConstantComposite:
|
||||
case spv::Op::OpSpecConstantOp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
|
||||
return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
|
||||
bool spvOpcodeIsConstantOrUndef(const spv::Op opcode) {
|
||||
return opcode == spv::Op::OpUndef || spvOpcodeIsConstant(opcode);
|
||||
}
|
||||
|
||||
bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode) {
|
||||
bool spvOpcodeIsScalarSpecConstant(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
case spv::Op::OpSpecConstantTrue:
|
||||
case spv::Op::OpSpecConstantFalse:
|
||||
case spv::Op::OpSpecConstant:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsComposite(const SpvOp opcode) {
|
||||
int32_t spvOpcodeIsComposite(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeStruct:
|
||||
case SpvOpTypeCooperativeMatrixNV:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeStruct:
|
||||
case spv::Op::OpTypeCooperativeMatrixNV:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode) {
|
||||
bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpVariable:
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpFunctionParameter:
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpCopyObject:
|
||||
case SpvOpSelect:
|
||||
case SpvOpPhi:
|
||||
case SpvOpFunctionCall:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpLoad:
|
||||
case SpvOpConstantNull:
|
||||
case spv::Op::OpVariable:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpFunctionParameter:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
case spv::Op::OpCopyObject:
|
||||
case spv::Op::OpSelect:
|
||||
case spv::Op::OpPhi:
|
||||
case spv::Op::OpFunctionCall:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpLoad:
|
||||
case spv::Op::OpConstantNull:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
|
||||
int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpVariable:
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpFunctionParameter:
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpCopyObject:
|
||||
case spv::Op::OpVariable:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpFunctionParameter:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
case spv::Op::OpCopyObject:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeGeneratesType(SpvOp op) {
|
||||
int32_t spvOpcodeGeneratesType(spv::Op op) {
|
||||
switch (op) {
|
||||
case SpvOpTypeVoid:
|
||||
case SpvOpTypeBool:
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeStruct:
|
||||
case SpvOpTypeOpaque:
|
||||
case SpvOpTypePointer:
|
||||
case SpvOpTypeFunction:
|
||||
case SpvOpTypeEvent:
|
||||
case SpvOpTypeDeviceEvent:
|
||||
case SpvOpTypeReserveId:
|
||||
case SpvOpTypeQueue:
|
||||
case SpvOpTypePipe:
|
||||
case SpvOpTypePipeStorage:
|
||||
case SpvOpTypeNamedBarrier:
|
||||
case SpvOpTypeAccelerationStructureNV:
|
||||
case SpvOpTypeCooperativeMatrixNV:
|
||||
// case SpvOpTypeAccelerationStructureKHR: covered by
|
||||
// SpvOpTypeAccelerationStructureNV
|
||||
case SpvOpTypeRayQueryKHR:
|
||||
case spv::Op::OpTypeVoid:
|
||||
case spv::Op::OpTypeBool:
|
||||
case spv::Op::OpTypeInt:
|
||||
case spv::Op::OpTypeFloat:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
case spv::Op::OpTypeImage:
|
||||
case spv::Op::OpTypeSampler:
|
||||
case spv::Op::OpTypeSampledImage:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeStruct:
|
||||
case spv::Op::OpTypeOpaque:
|
||||
case spv::Op::OpTypePointer:
|
||||
case spv::Op::OpTypeFunction:
|
||||
case spv::Op::OpTypeEvent:
|
||||
case spv::Op::OpTypeDeviceEvent:
|
||||
case spv::Op::OpTypeReserveId:
|
||||
case spv::Op::OpTypeQueue:
|
||||
case spv::Op::OpTypePipe:
|
||||
case spv::Op::OpTypePipeStorage:
|
||||
case spv::Op::OpTypeNamedBarrier:
|
||||
case spv::Op::OpTypeAccelerationStructureNV:
|
||||
case spv::Op::OpTypeCooperativeMatrixNV:
|
||||
// case spv::Op::OpTypeAccelerationStructureKHR: covered by
|
||||
// spv::Op::OpTypeAccelerationStructureNV
|
||||
case spv::Op::OpTypeRayQueryKHR:
|
||||
case spv::Op::OpTypeHitObjectNV:
|
||||
return true;
|
||||
default:
|
||||
// In particular, OpTypeForwardPointer does not generate a type,
|
||||
@@ -348,15 +353,15 @@ int32_t spvOpcodeGeneratesType(SpvOp op) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool spvOpcodeIsDecoration(const SpvOp opcode) {
|
||||
bool spvOpcodeIsDecoration(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case SpvOpMemberDecorateStringGOOGLE:
|
||||
case spv::Op::OpDecorate:
|
||||
case spv::Op::OpDecorateId:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
case spv::Op::OpGroupDecorate:
|
||||
case spv::Op::OpGroupMemberDecorate:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
case spv::Op::OpMemberDecorateStringGOOGLE:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
@@ -364,402 +369,403 @@ bool spvOpcodeIsDecoration(const SpvOp opcode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool spvOpcodeIsLoad(const SpvOp opcode) {
|
||||
bool spvOpcodeIsLoad(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpLoad:
|
||||
case SpvOpImageSampleExplicitLod:
|
||||
case SpvOpImageSampleImplicitLod:
|
||||
case SpvOpImageSampleDrefImplicitLod:
|
||||
case SpvOpImageSampleDrefExplicitLod:
|
||||
case SpvOpImageSampleProjImplicitLod:
|
||||
case SpvOpImageSampleProjExplicitLod:
|
||||
case SpvOpImageSampleProjDrefImplicitLod:
|
||||
case SpvOpImageSampleProjDrefExplicitLod:
|
||||
case SpvOpImageFetch:
|
||||
case SpvOpImageGather:
|
||||
case SpvOpImageDrefGather:
|
||||
case SpvOpImageRead:
|
||||
case SpvOpImageSparseSampleImplicitLod:
|
||||
case SpvOpImageSparseSampleExplicitLod:
|
||||
case SpvOpImageSparseSampleDrefExplicitLod:
|
||||
case SpvOpImageSparseSampleDrefImplicitLod:
|
||||
case SpvOpImageSparseFetch:
|
||||
case SpvOpImageSparseGather:
|
||||
case SpvOpImageSparseDrefGather:
|
||||
case SpvOpImageSparseRead:
|
||||
case spv::Op::OpLoad:
|
||||
case spv::Op::OpImageSampleExplicitLod:
|
||||
case spv::Op::OpImageSampleImplicitLod:
|
||||
case spv::Op::OpImageSampleDrefImplicitLod:
|
||||
case spv::Op::OpImageSampleDrefExplicitLod:
|
||||
case spv::Op::OpImageSampleProjImplicitLod:
|
||||
case spv::Op::OpImageSampleProjExplicitLod:
|
||||
case spv::Op::OpImageSampleProjDrefImplicitLod:
|
||||
case spv::Op::OpImageSampleProjDrefExplicitLod:
|
||||
case spv::Op::OpImageFetch:
|
||||
case spv::Op::OpImageGather:
|
||||
case spv::Op::OpImageDrefGather:
|
||||
case spv::Op::OpImageRead:
|
||||
case spv::Op::OpImageSparseSampleImplicitLod:
|
||||
case spv::Op::OpImageSparseSampleExplicitLod:
|
||||
case spv::Op::OpImageSparseSampleDrefExplicitLod:
|
||||
case spv::Op::OpImageSparseSampleDrefImplicitLod:
|
||||
case spv::Op::OpImageSparseFetch:
|
||||
case spv::Op::OpImageSparseGather:
|
||||
case spv::Op::OpImageSparseDrefGather:
|
||||
case spv::Op::OpImageSparseRead:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBranch(SpvOp opcode) {
|
||||
bool spvOpcodeIsBranch(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpBranch:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
case spv::Op::OpBranch:
|
||||
case spv::Op::OpBranchConditional:
|
||||
case spv::Op::OpSwitch:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode) {
|
||||
bool spvOpcodeIsAtomicWithLoad(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpAtomicLoad:
|
||||
case SpvOpAtomicExchange:
|
||||
case SpvOpAtomicCompareExchange:
|
||||
case SpvOpAtomicCompareExchangeWeak:
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
case SpvOpAtomicFMinEXT:
|
||||
case SpvOpAtomicSMax:
|
||||
case SpvOpAtomicUMax:
|
||||
case SpvOpAtomicFMaxEXT:
|
||||
case SpvOpAtomicAnd:
|
||||
case SpvOpAtomicOr:
|
||||
case SpvOpAtomicXor:
|
||||
case SpvOpAtomicFlagTestAndSet:
|
||||
case spv::Op::OpAtomicLoad:
|
||||
case spv::Op::OpAtomicExchange:
|
||||
case spv::Op::OpAtomicCompareExchange:
|
||||
case spv::Op::OpAtomicCompareExchangeWeak:
|
||||
case spv::Op::OpAtomicIIncrement:
|
||||
case spv::Op::OpAtomicIDecrement:
|
||||
case spv::Op::OpAtomicIAdd:
|
||||
case spv::Op::OpAtomicFAddEXT:
|
||||
case spv::Op::OpAtomicISub:
|
||||
case spv::Op::OpAtomicSMin:
|
||||
case spv::Op::OpAtomicUMin:
|
||||
case spv::Op::OpAtomicFMinEXT:
|
||||
case spv::Op::OpAtomicSMax:
|
||||
case spv::Op::OpAtomicUMax:
|
||||
case spv::Op::OpAtomicFMaxEXT:
|
||||
case spv::Op::OpAtomicAnd:
|
||||
case spv::Op::OpAtomicOr:
|
||||
case spv::Op::OpAtomicXor:
|
||||
case spv::Op::OpAtomicFlagTestAndSet:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsAtomicOp(const SpvOp opcode) {
|
||||
return (spvOpcodeIsAtomicWithLoad(opcode) || opcode == SpvOpAtomicStore ||
|
||||
opcode == SpvOpAtomicFlagClear);
|
||||
bool spvOpcodeIsAtomicOp(const spv::Op opcode) {
|
||||
return (spvOpcodeIsAtomicWithLoad(opcode) ||
|
||||
opcode == spv::Op::OpAtomicStore ||
|
||||
opcode == spv::Op::OpAtomicFlagClear);
|
||||
}
|
||||
|
||||
bool spvOpcodeIsReturn(SpvOp opcode) {
|
||||
bool spvOpcodeIsReturn(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpReturn:
|
||||
case SpvOpReturnValue:
|
||||
case spv::Op::OpReturn:
|
||||
case spv::Op::OpReturnValue:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsAbort(SpvOp opcode) {
|
||||
bool spvOpcodeIsAbort(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpKill:
|
||||
case SpvOpUnreachable:
|
||||
case SpvOpTerminateInvocation:
|
||||
case SpvOpTerminateRayKHR:
|
||||
case SpvOpIgnoreIntersectionKHR:
|
||||
case SpvOpEmitMeshTasksEXT:
|
||||
case spv::Op::OpKill:
|
||||
case spv::Op::OpUnreachable:
|
||||
case spv::Op::OpTerminateInvocation:
|
||||
case spv::Op::OpTerminateRayKHR:
|
||||
case spv::Op::OpIgnoreIntersectionKHR:
|
||||
case spv::Op::OpEmitMeshTasksEXT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
|
||||
bool spvOpcodeIsReturnOrAbort(spv::Op opcode) {
|
||||
return spvOpcodeIsReturn(opcode) || spvOpcodeIsAbort(opcode);
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
|
||||
bool spvOpcodeIsBlockTerminator(spv::Op opcode) {
|
||||
return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
|
||||
bool spvOpcodeIsBaseOpaqueType(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeOpaque:
|
||||
case SpvOpTypeEvent:
|
||||
case SpvOpTypeDeviceEvent:
|
||||
case SpvOpTypeReserveId:
|
||||
case SpvOpTypeQueue:
|
||||
case SpvOpTypePipe:
|
||||
case SpvOpTypeForwardPointer:
|
||||
case SpvOpTypePipeStorage:
|
||||
case SpvOpTypeNamedBarrier:
|
||||
case spv::Op::OpTypeImage:
|
||||
case spv::Op::OpTypeSampler:
|
||||
case spv::Op::OpTypeSampledImage:
|
||||
case spv::Op::OpTypeOpaque:
|
||||
case spv::Op::OpTypeEvent:
|
||||
case spv::Op::OpTypeDeviceEvent:
|
||||
case spv::Op::OpTypeReserveId:
|
||||
case spv::Op::OpTypeQueue:
|
||||
case spv::Op::OpTypePipe:
|
||||
case spv::Op::OpTypeForwardPointer:
|
||||
case spv::Op::OpTypePipeStorage:
|
||||
case spv::Op::OpTypeNamedBarrier:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode) {
|
||||
bool spvOpcodeIsNonUniformGroupOperation(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpGroupNonUniformElect:
|
||||
case SpvOpGroupNonUniformAll:
|
||||
case SpvOpGroupNonUniformAny:
|
||||
case SpvOpGroupNonUniformAllEqual:
|
||||
case SpvOpGroupNonUniformBroadcast:
|
||||
case SpvOpGroupNonUniformBroadcastFirst:
|
||||
case SpvOpGroupNonUniformBallot:
|
||||
case SpvOpGroupNonUniformInverseBallot:
|
||||
case SpvOpGroupNonUniformBallotBitExtract:
|
||||
case SpvOpGroupNonUniformBallotBitCount:
|
||||
case SpvOpGroupNonUniformBallotFindLSB:
|
||||
case SpvOpGroupNonUniformBallotFindMSB:
|
||||
case SpvOpGroupNonUniformShuffle:
|
||||
case SpvOpGroupNonUniformShuffleXor:
|
||||
case SpvOpGroupNonUniformShuffleUp:
|
||||
case SpvOpGroupNonUniformShuffleDown:
|
||||
case SpvOpGroupNonUniformIAdd:
|
||||
case SpvOpGroupNonUniformFAdd:
|
||||
case SpvOpGroupNonUniformIMul:
|
||||
case SpvOpGroupNonUniformFMul:
|
||||
case SpvOpGroupNonUniformSMin:
|
||||
case SpvOpGroupNonUniformUMin:
|
||||
case SpvOpGroupNonUniformFMin:
|
||||
case SpvOpGroupNonUniformSMax:
|
||||
case SpvOpGroupNonUniformUMax:
|
||||
case SpvOpGroupNonUniformFMax:
|
||||
case SpvOpGroupNonUniformBitwiseAnd:
|
||||
case SpvOpGroupNonUniformBitwiseOr:
|
||||
case SpvOpGroupNonUniformBitwiseXor:
|
||||
case SpvOpGroupNonUniformLogicalAnd:
|
||||
case SpvOpGroupNonUniformLogicalOr:
|
||||
case SpvOpGroupNonUniformLogicalXor:
|
||||
case SpvOpGroupNonUniformQuadBroadcast:
|
||||
case SpvOpGroupNonUniformQuadSwap:
|
||||
case SpvOpGroupNonUniformRotateKHR:
|
||||
case spv::Op::OpGroupNonUniformElect:
|
||||
case spv::Op::OpGroupNonUniformAll:
|
||||
case spv::Op::OpGroupNonUniformAny:
|
||||
case spv::Op::OpGroupNonUniformAllEqual:
|
||||
case spv::Op::OpGroupNonUniformBroadcast:
|
||||
case spv::Op::OpGroupNonUniformBroadcastFirst:
|
||||
case spv::Op::OpGroupNonUniformBallot:
|
||||
case spv::Op::OpGroupNonUniformInverseBallot:
|
||||
case spv::Op::OpGroupNonUniformBallotBitExtract:
|
||||
case spv::Op::OpGroupNonUniformBallotBitCount:
|
||||
case spv::Op::OpGroupNonUniformBallotFindLSB:
|
||||
case spv::Op::OpGroupNonUniformBallotFindMSB:
|
||||
case spv::Op::OpGroupNonUniformShuffle:
|
||||
case spv::Op::OpGroupNonUniformShuffleXor:
|
||||
case spv::Op::OpGroupNonUniformShuffleUp:
|
||||
case spv::Op::OpGroupNonUniformShuffleDown:
|
||||
case spv::Op::OpGroupNonUniformIAdd:
|
||||
case spv::Op::OpGroupNonUniformFAdd:
|
||||
case spv::Op::OpGroupNonUniformIMul:
|
||||
case spv::Op::OpGroupNonUniformFMul:
|
||||
case spv::Op::OpGroupNonUniformSMin:
|
||||
case spv::Op::OpGroupNonUniformUMin:
|
||||
case spv::Op::OpGroupNonUniformFMin:
|
||||
case spv::Op::OpGroupNonUniformSMax:
|
||||
case spv::Op::OpGroupNonUniformUMax:
|
||||
case spv::Op::OpGroupNonUniformFMax:
|
||||
case spv::Op::OpGroupNonUniformBitwiseAnd:
|
||||
case spv::Op::OpGroupNonUniformBitwiseOr:
|
||||
case spv::Op::OpGroupNonUniformBitwiseXor:
|
||||
case spv::Op::OpGroupNonUniformLogicalAnd:
|
||||
case spv::Op::OpGroupNonUniformLogicalOr:
|
||||
case spv::Op::OpGroupNonUniformLogicalXor:
|
||||
case spv::Op::OpGroupNonUniformQuadBroadcast:
|
||||
case spv::Op::OpGroupNonUniformQuadSwap:
|
||||
case spv::Op::OpGroupNonUniformRotateKHR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsScalarizable(SpvOp opcode) {
|
||||
bool spvOpcodeIsScalarizable(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpPhi:
|
||||
case SpvOpCopyObject:
|
||||
case SpvOpConvertFToU:
|
||||
case SpvOpConvertFToS:
|
||||
case SpvOpConvertSToF:
|
||||
case SpvOpConvertUToF:
|
||||
case SpvOpUConvert:
|
||||
case SpvOpSConvert:
|
||||
case SpvOpFConvert:
|
||||
case SpvOpQuantizeToF16:
|
||||
case SpvOpVectorInsertDynamic:
|
||||
case SpvOpSNegate:
|
||||
case SpvOpFNegate:
|
||||
case SpvOpIAdd:
|
||||
case SpvOpFAdd:
|
||||
case SpvOpISub:
|
||||
case SpvOpFSub:
|
||||
case SpvOpIMul:
|
||||
case SpvOpFMul:
|
||||
case SpvOpUDiv:
|
||||
case SpvOpSDiv:
|
||||
case SpvOpFDiv:
|
||||
case SpvOpUMod:
|
||||
case SpvOpSRem:
|
||||
case SpvOpSMod:
|
||||
case SpvOpFRem:
|
||||
case SpvOpFMod:
|
||||
case SpvOpVectorTimesScalar:
|
||||
case SpvOpIAddCarry:
|
||||
case SpvOpISubBorrow:
|
||||
case SpvOpUMulExtended:
|
||||
case SpvOpSMulExtended:
|
||||
case SpvOpShiftRightLogical:
|
||||
case SpvOpShiftRightArithmetic:
|
||||
case SpvOpShiftLeftLogical:
|
||||
case SpvOpBitwiseOr:
|
||||
case SpvOpBitwiseAnd:
|
||||
case SpvOpNot:
|
||||
case SpvOpBitFieldInsert:
|
||||
case SpvOpBitFieldSExtract:
|
||||
case SpvOpBitFieldUExtract:
|
||||
case SpvOpBitReverse:
|
||||
case SpvOpBitCount:
|
||||
case SpvOpIsNan:
|
||||
case SpvOpIsInf:
|
||||
case SpvOpIsFinite:
|
||||
case SpvOpIsNormal:
|
||||
case SpvOpSignBitSet:
|
||||
case SpvOpLessOrGreater:
|
||||
case SpvOpOrdered:
|
||||
case SpvOpUnordered:
|
||||
case SpvOpLogicalEqual:
|
||||
case SpvOpLogicalNotEqual:
|
||||
case SpvOpLogicalOr:
|
||||
case SpvOpLogicalAnd:
|
||||
case SpvOpLogicalNot:
|
||||
case SpvOpSelect:
|
||||
case SpvOpIEqual:
|
||||
case SpvOpINotEqual:
|
||||
case SpvOpUGreaterThan:
|
||||
case SpvOpSGreaterThan:
|
||||
case SpvOpUGreaterThanEqual:
|
||||
case SpvOpSGreaterThanEqual:
|
||||
case SpvOpULessThan:
|
||||
case SpvOpSLessThan:
|
||||
case SpvOpULessThanEqual:
|
||||
case SpvOpSLessThanEqual:
|
||||
case SpvOpFOrdEqual:
|
||||
case SpvOpFUnordEqual:
|
||||
case SpvOpFOrdNotEqual:
|
||||
case SpvOpFUnordNotEqual:
|
||||
case SpvOpFOrdLessThan:
|
||||
case SpvOpFUnordLessThan:
|
||||
case SpvOpFOrdGreaterThan:
|
||||
case SpvOpFUnordGreaterThan:
|
||||
case SpvOpFOrdLessThanEqual:
|
||||
case SpvOpFUnordLessThanEqual:
|
||||
case SpvOpFOrdGreaterThanEqual:
|
||||
case SpvOpFUnordGreaterThanEqual:
|
||||
case spv::Op::OpPhi:
|
||||
case spv::Op::OpCopyObject:
|
||||
case spv::Op::OpConvertFToU:
|
||||
case spv::Op::OpConvertFToS:
|
||||
case spv::Op::OpConvertSToF:
|
||||
case spv::Op::OpConvertUToF:
|
||||
case spv::Op::OpUConvert:
|
||||
case spv::Op::OpSConvert:
|
||||
case spv::Op::OpFConvert:
|
||||
case spv::Op::OpQuantizeToF16:
|
||||
case spv::Op::OpVectorInsertDynamic:
|
||||
case spv::Op::OpSNegate:
|
||||
case spv::Op::OpFNegate:
|
||||
case spv::Op::OpIAdd:
|
||||
case spv::Op::OpFAdd:
|
||||
case spv::Op::OpISub:
|
||||
case spv::Op::OpFSub:
|
||||
case spv::Op::OpIMul:
|
||||
case spv::Op::OpFMul:
|
||||
case spv::Op::OpUDiv:
|
||||
case spv::Op::OpSDiv:
|
||||
case spv::Op::OpFDiv:
|
||||
case spv::Op::OpUMod:
|
||||
case spv::Op::OpSRem:
|
||||
case spv::Op::OpSMod:
|
||||
case spv::Op::OpFRem:
|
||||
case spv::Op::OpFMod:
|
||||
case spv::Op::OpVectorTimesScalar:
|
||||
case spv::Op::OpIAddCarry:
|
||||
case spv::Op::OpISubBorrow:
|
||||
case spv::Op::OpUMulExtended:
|
||||
case spv::Op::OpSMulExtended:
|
||||
case spv::Op::OpShiftRightLogical:
|
||||
case spv::Op::OpShiftRightArithmetic:
|
||||
case spv::Op::OpShiftLeftLogical:
|
||||
case spv::Op::OpBitwiseOr:
|
||||
case spv::Op::OpBitwiseAnd:
|
||||
case spv::Op::OpNot:
|
||||
case spv::Op::OpBitFieldInsert:
|
||||
case spv::Op::OpBitFieldSExtract:
|
||||
case spv::Op::OpBitFieldUExtract:
|
||||
case spv::Op::OpBitReverse:
|
||||
case spv::Op::OpBitCount:
|
||||
case spv::Op::OpIsNan:
|
||||
case spv::Op::OpIsInf:
|
||||
case spv::Op::OpIsFinite:
|
||||
case spv::Op::OpIsNormal:
|
||||
case spv::Op::OpSignBitSet:
|
||||
case spv::Op::OpLessOrGreater:
|
||||
case spv::Op::OpOrdered:
|
||||
case spv::Op::OpUnordered:
|
||||
case spv::Op::OpLogicalEqual:
|
||||
case spv::Op::OpLogicalNotEqual:
|
||||
case spv::Op::OpLogicalOr:
|
||||
case spv::Op::OpLogicalAnd:
|
||||
case spv::Op::OpLogicalNot:
|
||||
case spv::Op::OpSelect:
|
||||
case spv::Op::OpIEqual:
|
||||
case spv::Op::OpINotEqual:
|
||||
case spv::Op::OpUGreaterThan:
|
||||
case spv::Op::OpSGreaterThan:
|
||||
case spv::Op::OpUGreaterThanEqual:
|
||||
case spv::Op::OpSGreaterThanEqual:
|
||||
case spv::Op::OpULessThan:
|
||||
case spv::Op::OpSLessThan:
|
||||
case spv::Op::OpULessThanEqual:
|
||||
case spv::Op::OpSLessThanEqual:
|
||||
case spv::Op::OpFOrdEqual:
|
||||
case spv::Op::OpFUnordEqual:
|
||||
case spv::Op::OpFOrdNotEqual:
|
||||
case spv::Op::OpFUnordNotEqual:
|
||||
case spv::Op::OpFOrdLessThan:
|
||||
case spv::Op::OpFUnordLessThan:
|
||||
case spv::Op::OpFOrdGreaterThan:
|
||||
case spv::Op::OpFUnordGreaterThan:
|
||||
case spv::Op::OpFOrdLessThanEqual:
|
||||
case spv::Op::OpFUnordLessThanEqual:
|
||||
case spv::Op::OpFOrdGreaterThanEqual:
|
||||
case spv::Op::OpFUnordGreaterThanEqual:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsDebug(SpvOp opcode) {
|
||||
bool spvOpcodeIsDebug(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpName:
|
||||
case SpvOpMemberName:
|
||||
case SpvOpSource:
|
||||
case SpvOpSourceContinued:
|
||||
case SpvOpSourceExtension:
|
||||
case SpvOpString:
|
||||
case SpvOpLine:
|
||||
case SpvOpNoLine:
|
||||
case SpvOpModuleProcessed:
|
||||
case spv::Op::OpName:
|
||||
case spv::Op::OpMemberName:
|
||||
case spv::Op::OpSource:
|
||||
case spv::Op::OpSourceContinued:
|
||||
case spv::Op::OpSourceExtension:
|
||||
case spv::Op::OpString:
|
||||
case spv::Op::OpLine:
|
||||
case spv::Op::OpNoLine:
|
||||
case spv::Op::OpModuleProcessed:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode) {
|
||||
bool spvOpcodeIsCommutativeBinaryOperator(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpPtrEqual:
|
||||
case SpvOpPtrNotEqual:
|
||||
case SpvOpIAdd:
|
||||
case SpvOpFAdd:
|
||||
case SpvOpIMul:
|
||||
case SpvOpFMul:
|
||||
case SpvOpDot:
|
||||
case SpvOpIAddCarry:
|
||||
case SpvOpUMulExtended:
|
||||
case SpvOpSMulExtended:
|
||||
case SpvOpBitwiseOr:
|
||||
case SpvOpBitwiseXor:
|
||||
case SpvOpBitwiseAnd:
|
||||
case SpvOpOrdered:
|
||||
case SpvOpUnordered:
|
||||
case SpvOpLogicalEqual:
|
||||
case SpvOpLogicalNotEqual:
|
||||
case SpvOpLogicalOr:
|
||||
case SpvOpLogicalAnd:
|
||||
case SpvOpIEqual:
|
||||
case SpvOpINotEqual:
|
||||
case SpvOpFOrdEqual:
|
||||
case SpvOpFUnordEqual:
|
||||
case SpvOpFOrdNotEqual:
|
||||
case SpvOpFUnordNotEqual:
|
||||
case spv::Op::OpPtrEqual:
|
||||
case spv::Op::OpPtrNotEqual:
|
||||
case spv::Op::OpIAdd:
|
||||
case spv::Op::OpFAdd:
|
||||
case spv::Op::OpIMul:
|
||||
case spv::Op::OpFMul:
|
||||
case spv::Op::OpDot:
|
||||
case spv::Op::OpIAddCarry:
|
||||
case spv::Op::OpUMulExtended:
|
||||
case spv::Op::OpSMulExtended:
|
||||
case spv::Op::OpBitwiseOr:
|
||||
case spv::Op::OpBitwiseXor:
|
||||
case spv::Op::OpBitwiseAnd:
|
||||
case spv::Op::OpOrdered:
|
||||
case spv::Op::OpUnordered:
|
||||
case spv::Op::OpLogicalEqual:
|
||||
case spv::Op::OpLogicalNotEqual:
|
||||
case spv::Op::OpLogicalOr:
|
||||
case spv::Op::OpLogicalAnd:
|
||||
case spv::Op::OpIEqual:
|
||||
case spv::Op::OpINotEqual:
|
||||
case spv::Op::OpFOrdEqual:
|
||||
case spv::Op::OpFUnordEqual:
|
||||
case spv::Op::OpFOrdNotEqual:
|
||||
case spv::Op::OpFUnordNotEqual:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsLinearAlgebra(SpvOp opcode) {
|
||||
bool spvOpcodeIsLinearAlgebra(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpTranspose:
|
||||
case SpvOpVectorTimesScalar:
|
||||
case SpvOpMatrixTimesScalar:
|
||||
case SpvOpVectorTimesMatrix:
|
||||
case SpvOpMatrixTimesVector:
|
||||
case SpvOpMatrixTimesMatrix:
|
||||
case SpvOpOuterProduct:
|
||||
case SpvOpDot:
|
||||
case spv::Op::OpTranspose:
|
||||
case spv::Op::OpVectorTimesScalar:
|
||||
case spv::Op::OpMatrixTimesScalar:
|
||||
case spv::Op::OpVectorTimesMatrix:
|
||||
case spv::Op::OpMatrixTimesVector:
|
||||
case spv::Op::OpMatrixTimesMatrix:
|
||||
case spv::Op::OpOuterProduct:
|
||||
case spv::Op::OpDot:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsImageSample(const SpvOp opcode) {
|
||||
bool spvOpcodeIsImageSample(const spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpImageSampleImplicitLod:
|
||||
case SpvOpImageSampleExplicitLod:
|
||||
case SpvOpImageSampleDrefImplicitLod:
|
||||
case SpvOpImageSampleDrefExplicitLod:
|
||||
case SpvOpImageSampleProjImplicitLod:
|
||||
case SpvOpImageSampleProjExplicitLod:
|
||||
case SpvOpImageSampleProjDrefImplicitLod:
|
||||
case SpvOpImageSampleProjDrefExplicitLod:
|
||||
case SpvOpImageSparseSampleImplicitLod:
|
||||
case SpvOpImageSparseSampleExplicitLod:
|
||||
case SpvOpImageSparseSampleDrefImplicitLod:
|
||||
case SpvOpImageSparseSampleDrefExplicitLod:
|
||||
case spv::Op::OpImageSampleImplicitLod:
|
||||
case spv::Op::OpImageSampleExplicitLod:
|
||||
case spv::Op::OpImageSampleDrefImplicitLod:
|
||||
case spv::Op::OpImageSampleDrefExplicitLod:
|
||||
case spv::Op::OpImageSampleProjImplicitLod:
|
||||
case spv::Op::OpImageSampleProjExplicitLod:
|
||||
case spv::Op::OpImageSampleProjDrefImplicitLod:
|
||||
case spv::Op::OpImageSampleProjDrefExplicitLod:
|
||||
case spv::Op::OpImageSparseSampleImplicitLod:
|
||||
case spv::Op::OpImageSparseSampleExplicitLod:
|
||||
case spv::Op::OpImageSparseSampleDrefImplicitLod:
|
||||
case spv::Op::OpImageSparseSampleDrefExplicitLod:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
|
||||
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpMemoryBarrier:
|
||||
case spv::Op::OpMemoryBarrier:
|
||||
return {1};
|
||||
case SpvOpAtomicStore:
|
||||
case SpvOpControlBarrier:
|
||||
case SpvOpAtomicFlagClear:
|
||||
case SpvOpMemoryNamedBarrier:
|
||||
case spv::Op::OpAtomicStore:
|
||||
case spv::Op::OpControlBarrier:
|
||||
case spv::Op::OpAtomicFlagClear:
|
||||
case spv::Op::OpMemoryNamedBarrier:
|
||||
return {2};
|
||||
case SpvOpAtomicLoad:
|
||||
case SpvOpAtomicExchange:
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
case SpvOpAtomicSMax:
|
||||
case SpvOpAtomicUMax:
|
||||
case SpvOpAtomicAnd:
|
||||
case SpvOpAtomicOr:
|
||||
case SpvOpAtomicXor:
|
||||
case SpvOpAtomicFlagTestAndSet:
|
||||
case spv::Op::OpAtomicLoad:
|
||||
case spv::Op::OpAtomicExchange:
|
||||
case spv::Op::OpAtomicIIncrement:
|
||||
case spv::Op::OpAtomicIDecrement:
|
||||
case spv::Op::OpAtomicIAdd:
|
||||
case spv::Op::OpAtomicFAddEXT:
|
||||
case spv::Op::OpAtomicISub:
|
||||
case spv::Op::OpAtomicSMin:
|
||||
case spv::Op::OpAtomicUMin:
|
||||
case spv::Op::OpAtomicSMax:
|
||||
case spv::Op::OpAtomicUMax:
|
||||
case spv::Op::OpAtomicAnd:
|
||||
case spv::Op::OpAtomicOr:
|
||||
case spv::Op::OpAtomicXor:
|
||||
case spv::Op::OpAtomicFlagTestAndSet:
|
||||
return {4};
|
||||
case SpvOpAtomicCompareExchange:
|
||||
case SpvOpAtomicCompareExchangeWeak:
|
||||
case spv::Op::OpAtomicCompareExchange:
|
||||
case spv::Op::OpAtomicCompareExchangeWeak:
|
||||
return {4, 5};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsAccessChain(SpvOp opcode) {
|
||||
bool spvOpcodeIsAccessChain(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBit(SpvOp opcode) {
|
||||
bool spvOpcodeIsBit(spv::Op opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpShiftRightLogical:
|
||||
case SpvOpShiftRightArithmetic:
|
||||
case SpvOpShiftLeftLogical:
|
||||
case SpvOpBitwiseOr:
|
||||
case SpvOpBitwiseXor:
|
||||
case SpvOpBitwiseAnd:
|
||||
case SpvOpNot:
|
||||
case SpvOpBitReverse:
|
||||
case SpvOpBitCount:
|
||||
case spv::Op::OpShiftRightLogical:
|
||||
case spv::Op::OpShiftRightArithmetic:
|
||||
case spv::Op::OpShiftLeftLogical:
|
||||
case spv::Op::OpBitwiseOr:
|
||||
case spv::Op::OpBitwiseXor:
|
||||
case spv::Op::OpBitwiseAnd:
|
||||
case spv::Op::OpNot:
|
||||
case spv::Op::OpBitReverse:
|
||||
case spv::Op::OpBitCount:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
65
3rdparty/spirv-tools/source/opcode.h
vendored
65
3rdparty/spirv-tools/source/opcode.h
vendored
@@ -29,7 +29,7 @@
|
||||
const char* spvGeneratorStr(uint32_t generator);
|
||||
|
||||
// Combines word_count and opcode enumerant in single word.
|
||||
uint32_t spvOpcodeMake(uint16_t word_count, SpvOp opcode);
|
||||
uint32_t spvOpcodeMake(uint16_t word_count, spv::Op opcode);
|
||||
|
||||
// Splits word into into two constituent parts: word_count and opcode.
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t* word_count,
|
||||
@@ -45,115 +45,118 @@ spv_result_t spvOpcodeTableNameLookup(spv_target_env,
|
||||
// SPV_SUCCESS and writes a handle of the table entry into *entry.
|
||||
spv_result_t spvOpcodeTableValueLookup(spv_target_env,
|
||||
const spv_opcode_table table,
|
||||
const SpvOp opcode,
|
||||
const spv::Op opcode,
|
||||
spv_opcode_desc* entry);
|
||||
|
||||
// Copies an instruction's word and fixes the endianness to host native. The
|
||||
// source instruction's stream/opcode/endianness is in the words/opcode/endian
|
||||
// parameter. The word_count parameter specifies the number of words to copy.
|
||||
// Writes copied instruction into *inst.
|
||||
void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
|
||||
const uint16_t word_count,
|
||||
const spv_endianness_t endian, spv_instruction_t* inst);
|
||||
|
||||
// Determine if the given opcode is a scalar type. Returns zero if false,
|
||||
// non-zero otherwise.
|
||||
int32_t spvOpcodeIsScalarType(const SpvOp opcode);
|
||||
int32_t spvOpcodeIsScalarType(const spv::Op opcode);
|
||||
|
||||
// Determines if the given opcode is a specialization constant. Returns zero if
|
||||
// false, non-zero otherwise.
|
||||
int32_t spvOpcodeIsSpecConstant(const SpvOp opcode);
|
||||
int32_t spvOpcodeIsSpecConstant(const spv::Op opcode);
|
||||
|
||||
// Determines if the given opcode is a constant. Returns zero if false, non-zero
|
||||
// otherwise.
|
||||
int32_t spvOpcodeIsConstant(const SpvOp opcode);
|
||||
int32_t spvOpcodeIsConstant(const spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a constant or undef.
|
||||
bool spvOpcodeIsConstantOrUndef(const SpvOp opcode);
|
||||
bool spvOpcodeIsConstantOrUndef(const spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a scalar specialization constant.
|
||||
bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode);
|
||||
bool spvOpcodeIsScalarSpecConstant(const spv::Op opcode);
|
||||
|
||||
// Determines if the given opcode is a composite type. Returns zero if false,
|
||||
// non-zero otherwise.
|
||||
int32_t spvOpcodeIsComposite(const SpvOp opcode);
|
||||
int32_t spvOpcodeIsComposite(const spv::Op opcode);
|
||||
|
||||
// Determines if the given opcode results in a pointer when using the logical
|
||||
// addressing model. Returns zero if false, non-zero otherwise.
|
||||
int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode);
|
||||
int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode);
|
||||
|
||||
// Returns whether the given opcode could result in a pointer or a variable
|
||||
// pointer when using the logical addressing model.
|
||||
bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode);
|
||||
bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode);
|
||||
|
||||
// Determines if the given opcode generates a type. Returns zero if false,
|
||||
// non-zero otherwise.
|
||||
int32_t spvOpcodeGeneratesType(SpvOp opcode);
|
||||
int32_t spvOpcodeGeneratesType(spv::Op opcode);
|
||||
|
||||
// Returns true if the opcode adds a decoration to an id.
|
||||
bool spvOpcodeIsDecoration(const SpvOp opcode);
|
||||
bool spvOpcodeIsDecoration(const spv::Op opcode);
|
||||
|
||||
// Returns true if the opcode is a load from memory into a result id. This
|
||||
// function only considers core instructions.
|
||||
bool spvOpcodeIsLoad(const SpvOp opcode);
|
||||
bool spvOpcodeIsLoad(const spv::Op opcode);
|
||||
|
||||
// Returns true if the opcode is an atomic operation that uses the original
|
||||
// value.
|
||||
bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode);
|
||||
bool spvOpcodeIsAtomicWithLoad(const spv::Op opcode);
|
||||
|
||||
// Returns true if the opcode is an atomic operation.
|
||||
bool spvOpcodeIsAtomicOp(const SpvOp opcode);
|
||||
bool spvOpcodeIsAtomicOp(const spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a branch instruction.
|
||||
bool spvOpcodeIsBranch(SpvOp opcode);
|
||||
bool spvOpcodeIsBranch(spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a return instruction.
|
||||
bool spvOpcodeIsReturn(SpvOp opcode);
|
||||
bool spvOpcodeIsReturn(spv::Op opcode);
|
||||
|
||||
// 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);
|
||||
bool spvOpcodeIsAbort(spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a return instruction or it aborts
|
||||
// execution.
|
||||
bool spvOpcodeIsReturnOrAbort(SpvOp opcode);
|
||||
bool spvOpcodeIsReturnOrAbort(spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a basic block terminator.
|
||||
bool spvOpcodeIsBlockTerminator(SpvOp opcode);
|
||||
bool spvOpcodeIsBlockTerminator(spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode always defines an opaque type.
|
||||
bool spvOpcodeIsBaseOpaqueType(SpvOp opcode);
|
||||
bool spvOpcodeIsBaseOpaqueType(spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a non-uniform group operation.
|
||||
bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode);
|
||||
bool spvOpcodeIsNonUniformGroupOperation(spv::Op opcode);
|
||||
|
||||
// Returns true if the opcode with vector inputs could be divided into a series
|
||||
// of independent scalar operations that would give the same result.
|
||||
bool spvOpcodeIsScalarizable(SpvOp opcode);
|
||||
bool spvOpcodeIsScalarizable(spv::Op opcode);
|
||||
|
||||
// Returns true if the given opcode is a debug instruction.
|
||||
bool spvOpcodeIsDebug(SpvOp opcode);
|
||||
bool spvOpcodeIsDebug(spv::Op opcode);
|
||||
|
||||
// Returns true for opcodes that are binary operators,
|
||||
// where the order of the operands is irrelevant.
|
||||
bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode);
|
||||
bool spvOpcodeIsCommutativeBinaryOperator(spv::Op opcode);
|
||||
|
||||
// Returns true for opcodes that represent linear algebra instructions.
|
||||
bool spvOpcodeIsLinearAlgebra(SpvOp opcode);
|
||||
bool spvOpcodeIsLinearAlgebra(spv::Op opcode);
|
||||
|
||||
// Returns true for opcodes that represent image sample instructions.
|
||||
bool spvOpcodeIsImageSample(SpvOp opcode);
|
||||
bool spvOpcodeIsImageSample(spv::Op opcode);
|
||||
|
||||
// Returns a vector containing the indices of the memory semantics <id>
|
||||
// operands for |opcode|.
|
||||
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);
|
||||
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode);
|
||||
|
||||
// Returns true for opcodes that represent access chain instructions.
|
||||
bool spvOpcodeIsAccessChain(SpvOp opcode);
|
||||
bool spvOpcodeIsAccessChain(spv::Op opcode);
|
||||
|
||||
// Returns true for opcodes that represent bit instructions.
|
||||
bool spvOpcodeIsBit(SpvOp opcode);
|
||||
bool spvOpcodeIsBit(spv::Op opcode);
|
||||
|
||||
// Gets the name of an instruction, without the "Op" prefix.
|
||||
const char* spvOpcodeString(const spv::Op opcode);
|
||||
|
||||
#endif // SOURCE_OPCODE_H_
|
||||
|
||||
54
3rdparty/spirv-tools/source/operand.cpp
vendored
54
3rdparty/spirv-tools/source/operand.cpp
vendored
@@ -512,7 +512,7 @@ bool spvIsInIdType(spv_operand_type_t type) {
|
||||
}
|
||||
|
||||
std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
SpvOp opcode) {
|
||||
spv::Op opcode) {
|
||||
std::function<bool(unsigned index)> out;
|
||||
if (spvOpcodeGeneratesType(opcode)) {
|
||||
// All types can use forward pointers.
|
||||
@@ -520,57 +520,57 @@ std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
return out;
|
||||
}
|
||||
switch (opcode) {
|
||||
case SpvOpExecutionMode:
|
||||
case SpvOpExecutionModeId:
|
||||
case SpvOpEntryPoint:
|
||||
case SpvOpName:
|
||||
case SpvOpMemberName:
|
||||
case SpvOpSelectionMerge:
|
||||
case SpvOpDecorate:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case SpvOpMemberDecorateStringGOOGLE:
|
||||
case SpvOpBranch:
|
||||
case SpvOpLoopMerge:
|
||||
case spv::Op::OpExecutionMode:
|
||||
case spv::Op::OpExecutionModeId:
|
||||
case spv::Op::OpEntryPoint:
|
||||
case spv::Op::OpName:
|
||||
case spv::Op::OpMemberName:
|
||||
case spv::Op::OpSelectionMerge:
|
||||
case spv::Op::OpDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
case spv::Op::OpDecorateId:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
case spv::Op::OpMemberDecorateStringGOOGLE:
|
||||
case spv::Op::OpBranch:
|
||||
case spv::Op::OpLoopMerge:
|
||||
out = [](unsigned) { return true; };
|
||||
break;
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
case spv::Op::OpGroupDecorate:
|
||||
case spv::Op::OpGroupMemberDecorate:
|
||||
case spv::Op::OpBranchConditional:
|
||||
case spv::Op::OpSwitch:
|
||||
out = [](unsigned index) { return index != 0; };
|
||||
break;
|
||||
|
||||
case SpvOpFunctionCall:
|
||||
case spv::Op::OpFunctionCall:
|
||||
// The Function parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
|
||||
case SpvOpPhi:
|
||||
case spv::Op::OpPhi:
|
||||
out = [](unsigned index) { return index > 1; };
|
||||
break;
|
||||
|
||||
case SpvOpEnqueueKernel:
|
||||
case spv::Op::OpEnqueueKernel:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 8; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelNDrangeSubGroupCount:
|
||||
case SpvOpGetKernelNDrangeMaxSubGroupSize:
|
||||
case spv::Op::OpGetKernelNDrangeSubGroupCount:
|
||||
case spv::Op::OpGetKernelNDrangeMaxSubGroupSize:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 3; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelWorkGroupSize:
|
||||
case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
|
||||
case spv::Op::OpGetKernelWorkGroupSize:
|
||||
case spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
case SpvOpTypeForwardPointer:
|
||||
case spv::Op::OpTypeForwardPointer:
|
||||
out = [](unsigned index) { return index == 0; };
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
out = [](unsigned index) { return index == 1; };
|
||||
break;
|
||||
default:
|
||||
|
||||
2
3rdparty/spirv-tools/source/operand.h
vendored
2
3rdparty/spirv-tools/source/operand.h
vendored
@@ -139,7 +139,7 @@ bool spvIsInIdType(spv_operand_type_t type);
|
||||
// of the operand can be forward declared. This function will
|
||||
// used in the SSA validation stage of the pipeline
|
||||
std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
SpvOp opcode);
|
||||
spv::Op opcode);
|
||||
|
||||
// Takes the instruction key of a debug info extension instruction
|
||||
// and returns a function object that will return true if the index
|
||||
|
||||
@@ -31,51 +31,50 @@
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kTypePointerStorageClassInIdx = 0;
|
||||
const uint32_t kEntryPointFunctionIdInIdx = 1;
|
||||
const uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
|
||||
const uint32_t kLoopMergeContinueBlockIdInIdx = 1;
|
||||
const uint32_t kCopyMemoryTargetAddrInIdx = 0;
|
||||
const uint32_t kCopyMemorySourceAddrInIdx = 1;
|
||||
const uint32_t kLoadSourceAddrInIdx = 0;
|
||||
const uint32_t kDebugDeclareOperandVariableIndex = 5;
|
||||
const uint32_t kGlobalVariableVariableIndex = 12;
|
||||
constexpr uint32_t kTypePointerStorageClassInIdx = 0;
|
||||
constexpr uint32_t kEntryPointFunctionIdInIdx = 1;
|
||||
constexpr uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
|
||||
constexpr uint32_t kLoopMergeContinueBlockIdInIdx = 1;
|
||||
constexpr uint32_t kCopyMemoryTargetAddrInIdx = 0;
|
||||
constexpr uint32_t kCopyMemorySourceAddrInIdx = 1;
|
||||
constexpr uint32_t kLoadSourceAddrInIdx = 0;
|
||||
constexpr uint32_t kDebugDeclareOperandVariableIndex = 5;
|
||||
constexpr uint32_t kGlobalVariableVariableIndex = 12;
|
||||
|
||||
// Sorting functor to present annotation instructions in an easy-to-process
|
||||
// order. The functor orders by opcode first and falls back on unique id
|
||||
// ordering if both instructions have the same opcode.
|
||||
//
|
||||
// Desired priority:
|
||||
// SpvOpGroupDecorate
|
||||
// SpvOpGroupMemberDecorate
|
||||
// SpvOpDecorate
|
||||
// SpvOpMemberDecorate
|
||||
// SpvOpDecorateId
|
||||
// SpvOpDecorateStringGOOGLE
|
||||
// SpvOpDecorationGroup
|
||||
// spv::Op::OpGroupDecorate
|
||||
// spv::Op::OpGroupMemberDecorate
|
||||
// spv::Op::OpDecorate
|
||||
// spv::Op::OpMemberDecorate
|
||||
// spv::Op::OpDecorateId
|
||||
// spv::Op::OpDecorateStringGOOGLE
|
||||
// spv::Op::OpDecorationGroup
|
||||
struct DecorationLess {
|
||||
bool operator()(const Instruction* lhs, const Instruction* rhs) const {
|
||||
assert(lhs && rhs);
|
||||
SpvOp lhsOp = lhs->opcode();
|
||||
SpvOp rhsOp = rhs->opcode();
|
||||
spv::Op lhsOp = lhs->opcode();
|
||||
spv::Op rhsOp = rhs->opcode();
|
||||
if (lhsOp != rhsOp) {
|
||||
#define PRIORITY_CASE(opcode) \
|
||||
if (lhsOp == opcode && rhsOp != opcode) return true; \
|
||||
if (rhsOp == opcode && lhsOp != opcode) return false;
|
||||
// OpGroupDecorate and OpGroupMember decorate are highest priority to
|
||||
// eliminate dead targets early and simplify subsequent checks.
|
||||
PRIORITY_CASE(SpvOpGroupDecorate)
|
||||
PRIORITY_CASE(SpvOpGroupMemberDecorate)
|
||||
PRIORITY_CASE(SpvOpDecorate)
|
||||
PRIORITY_CASE(SpvOpMemberDecorate)
|
||||
PRIORITY_CASE(SpvOpDecorateId)
|
||||
PRIORITY_CASE(SpvOpDecorateStringGOOGLE)
|
||||
PRIORITY_CASE(spv::Op::OpGroupDecorate)
|
||||
PRIORITY_CASE(spv::Op::OpGroupMemberDecorate)
|
||||
PRIORITY_CASE(spv::Op::OpDecorate)
|
||||
PRIORITY_CASE(spv::Op::OpMemberDecorate)
|
||||
PRIORITY_CASE(spv::Op::OpDecorateId)
|
||||
PRIORITY_CASE(spv::Op::OpDecorateStringGOOGLE)
|
||||
// OpDecorationGroup is lowest priority to ensure use/def chains remain
|
||||
// usable for instructions that target this group.
|
||||
PRIORITY_CASE(SpvOpDecorationGroup)
|
||||
PRIORITY_CASE(spv::Op::OpDecorationGroup)
|
||||
#undef PRIORITY_CASE
|
||||
}
|
||||
|
||||
@@ -86,25 +85,26 @@ struct DecorationLess {
|
||||
|
||||
} // namespace
|
||||
|
||||
bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId, uint32_t storageClass) {
|
||||
bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId,
|
||||
spv::StorageClass storageClass) {
|
||||
if (varId == 0) return false;
|
||||
const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
|
||||
const SpvOp op = varInst->opcode();
|
||||
if (op != SpvOpVariable) return false;
|
||||
const spv::Op op = varInst->opcode();
|
||||
if (op != spv::Op::OpVariable) return false;
|
||||
const uint32_t varTypeId = varInst->type_id();
|
||||
const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
|
||||
if (varTypeInst->opcode() != SpvOpTypePointer) return false;
|
||||
return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
|
||||
storageClass;
|
||||
if (varTypeInst->opcode() != spv::Op::OpTypePointer) return false;
|
||||
return spv::StorageClass(varTypeInst->GetSingleWordInOperand(
|
||||
kTypePointerStorageClassInIdx)) == storageClass;
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::IsLocalVar(uint32_t varId, Function* func) {
|
||||
if (IsVarOfStorage(varId, SpvStorageClassFunction)) {
|
||||
if (IsVarOfStorage(varId, spv::StorageClass::Function)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsVarOfStorage(varId, SpvStorageClassPrivate) &&
|
||||
!IsVarOfStorage(varId, SpvStorageClassWorkgroup)) {
|
||||
if (!IsVarOfStorage(varId, spv::StorageClass::Private) &&
|
||||
!IsVarOfStorage(varId, spv::StorageClass::Workgroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,21 +122,21 @@ void AggressiveDCEPass::AddStores(Function* func, uint32_t ptrId) {
|
||||
if (blk && blk->GetParent() != func) return;
|
||||
|
||||
switch (user->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpCopyObject:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpCopyObject:
|
||||
this->AddStores(func, user->result_id());
|
||||
break;
|
||||
case SpvOpLoad:
|
||||
case spv::Op::OpLoad:
|
||||
break;
|
||||
case SpvOpCopyMemory:
|
||||
case SpvOpCopyMemorySized:
|
||||
case spv::Op::OpCopyMemory:
|
||||
case spv::Op::OpCopyMemorySized:
|
||||
if (user->GetSingleWordInOperand(kCopyMemoryTargetAddrInIdx) == ptrId) {
|
||||
AddToWorklist(user);
|
||||
}
|
||||
break;
|
||||
// If default, assume it stores e.g. frexp, modf, function call
|
||||
case SpvOpStore:
|
||||
case spv::Op::OpStore:
|
||||
default:
|
||||
AddToWorklist(user);
|
||||
break;
|
||||
@@ -154,7 +154,7 @@ bool AggressiveDCEPass::AllExtensionsSupported() const {
|
||||
// Only allow NonSemantic.Shader.DebugInfo.100, we cannot safely optimise
|
||||
// around unknown extended instruction sets even if they are non-semantic
|
||||
for (auto& inst : context()->module()->ext_inst_imports()) {
|
||||
assert(inst.opcode() == SpvOpExtInstImport &&
|
||||
assert(inst.opcode() == spv::Op::OpExtInstImport &&
|
||||
"Expecting an import of an extension's instruction set.");
|
||||
const std::string extension_name = inst.GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
|
||||
@@ -172,11 +172,11 @@ bool AggressiveDCEPass::IsTargetDead(Instruction* inst) {
|
||||
// This must be a decoration group. We go through annotations in a specific
|
||||
// order. So if this is not used by any group or group member decorates, it
|
||||
// is dead.
|
||||
assert(tInst->opcode() == SpvOpDecorationGroup);
|
||||
assert(tInst->opcode() == spv::Op::OpDecorationGroup);
|
||||
bool dead = true;
|
||||
get_def_use_mgr()->ForEachUser(tInst, [&dead](Instruction* user) {
|
||||
if (user->opcode() == SpvOpGroupDecorate ||
|
||||
user->opcode() == SpvOpGroupMemberDecorate)
|
||||
if (user->opcode() == spv::Op::OpGroupDecorate ||
|
||||
user->opcode() == spv::Op::OpGroupMemberDecorate)
|
||||
dead = false;
|
||||
});
|
||||
return dead;
|
||||
@@ -197,7 +197,7 @@ void AggressiveDCEPass::ProcessLoad(Function* func, uint32_t varId) {
|
||||
|
||||
void AggressiveDCEPass::AddBranch(uint32_t labelId, BasicBlock* bp) {
|
||||
std::unique_ptr<Instruction> newBranch(
|
||||
new Instruction(context(), SpvOpBranch, 0, 0,
|
||||
new Instruction(context(), spv::Op::OpBranch, 0, 0,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}}));
|
||||
context()->AnalyzeDefUse(&*newBranch);
|
||||
context()->set_instr_block(&*newBranch, bp);
|
||||
@@ -206,8 +206,8 @@ void AggressiveDCEPass::AddBranch(uint32_t labelId, BasicBlock* bp) {
|
||||
|
||||
void AggressiveDCEPass::AddBreaksAndContinuesToWorklist(
|
||||
Instruction* mergeInst) {
|
||||
assert(mergeInst->opcode() == SpvOpSelectionMerge ||
|
||||
mergeInst->opcode() == SpvOpLoopMerge);
|
||||
assert(mergeInst->opcode() == spv::Op::OpSelectionMerge ||
|
||||
mergeInst->opcode() == spv::Op::OpLoopMerge);
|
||||
|
||||
BasicBlock* header = context()->get_instr_block(mergeInst);
|
||||
const uint32_t mergeId = mergeInst->GetSingleWordInOperand(0);
|
||||
@@ -223,7 +223,7 @@ void AggressiveDCEPass::AddBreaksAndContinuesToWorklist(
|
||||
}
|
||||
});
|
||||
|
||||
if (mergeInst->opcode() != SpvOpLoopMerge) {
|
||||
if (mergeInst->opcode() != spv::Op::OpLoopMerge) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -231,26 +231,27 @@ void AggressiveDCEPass::AddBreaksAndContinuesToWorklist(
|
||||
const uint32_t contId =
|
||||
mergeInst->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
|
||||
get_def_use_mgr()->ForEachUser(contId, [&contId, this](Instruction* user) {
|
||||
SpvOp op = user->opcode();
|
||||
if (op == SpvOpBranchConditional || op == SpvOpSwitch) {
|
||||
spv::Op op = user->opcode();
|
||||
if (op == spv::Op::OpBranchConditional || op == spv::Op::OpSwitch) {
|
||||
// A conditional branch or switch can only be a continue if it does not
|
||||
// have a merge instruction or its merge block is not the continue block.
|
||||
Instruction* hdrMerge = GetMergeInstruction(user);
|
||||
if (hdrMerge != nullptr && hdrMerge->opcode() == SpvOpSelectionMerge) {
|
||||
if (hdrMerge != nullptr &&
|
||||
hdrMerge->opcode() == spv::Op::OpSelectionMerge) {
|
||||
uint32_t hdrMergeId =
|
||||
hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
|
||||
if (hdrMergeId == contId) return;
|
||||
// Need to mark merge instruction too
|
||||
AddToWorklist(hdrMerge);
|
||||
}
|
||||
} else if (op == SpvOpBranch) {
|
||||
} else if (op == spv::Op::OpBranch) {
|
||||
// An unconditional branch can only be a continue if it is not
|
||||
// branching to its own merge block.
|
||||
BasicBlock* blk = context()->get_instr_block(user);
|
||||
Instruction* hdrBranch = GetHeaderBranch(blk);
|
||||
if (hdrBranch == nullptr) return;
|
||||
Instruction* hdrMerge = GetMergeInstruction(hdrBranch);
|
||||
if (hdrMerge->opcode() == SpvOpLoopMerge) return;
|
||||
if (hdrMerge->opcode() == spv::Op::OpLoopMerge) return;
|
||||
uint32_t hdrMergeId =
|
||||
hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
|
||||
if (contId == hdrMergeId) return;
|
||||
@@ -277,11 +278,11 @@ bool AggressiveDCEPass::KillDeadInstructions(
|
||||
uint32_t merge_block_id = 0;
|
||||
(*bi)->ForEachInst([this, &modified, &merge_block_id](Instruction* inst) {
|
||||
if (IsLive(inst)) return;
|
||||
if (inst->opcode() == SpvOpLabel) return;
|
||||
if (inst->opcode() == spv::Op::OpLabel) return;
|
||||
// If dead instruction is selection merge, remember merge block
|
||||
// for new branch at end of block
|
||||
if (inst->opcode() == SpvOpSelectionMerge ||
|
||||
inst->opcode() == SpvOpLoopMerge)
|
||||
if (inst->opcode() == spv::Op::OpSelectionMerge ||
|
||||
inst->opcode() == spv::Op::OpLoopMerge)
|
||||
merge_block_id = inst->GetSingleWordInOperand(0);
|
||||
to_kill_.push_back(inst);
|
||||
modified = true;
|
||||
@@ -295,19 +296,19 @@ bool AggressiveDCEPass::KillDeadInstructions(
|
||||
}
|
||||
|
||||
auto merge_terminator = (*bi)->terminator();
|
||||
if (merge_terminator->opcode() == SpvOpUnreachable) {
|
||||
if (merge_terminator->opcode() == spv::Op::OpUnreachable) {
|
||||
// The merge was unreachable. This is undefined behaviour so just
|
||||
// return (or return an undef). Then mark the new return as live.
|
||||
auto func_ret_type_inst = get_def_use_mgr()->GetDef(func->type_id());
|
||||
if (func_ret_type_inst->opcode() == SpvOpTypeVoid) {
|
||||
merge_terminator->SetOpcode(SpvOpReturn);
|
||||
if (func_ret_type_inst->opcode() == spv::Op::OpTypeVoid) {
|
||||
merge_terminator->SetOpcode(spv::Op::OpReturn);
|
||||
} else {
|
||||
// Find an undef for the return value and make sure it gets kept by
|
||||
// the pass.
|
||||
auto undef_id = Type2Undef(func->type_id());
|
||||
auto undef = get_def_use_mgr()->GetDef(undef_id);
|
||||
live_insts_.Set(undef->unique_id());
|
||||
merge_terminator->SetOpcode(SpvOpReturnValue);
|
||||
merge_terminator->SetOpcode(spv::Op::OpReturnValue);
|
||||
merge_terminator->SetInOperands({{SPV_OPERAND_TYPE_ID, {undef_id}}});
|
||||
get_def_use_mgr()->AnalyzeInstUse(merge_terminator);
|
||||
}
|
||||
@@ -369,11 +370,11 @@ void AggressiveDCEPass::AddDecorationsToWorkList(const Instruction* inst) {
|
||||
// We only care about OpDecorateId instructions because the are the only
|
||||
// decorations that will reference an id that will have to be kept live
|
||||
// because of that use.
|
||||
if (dec->opcode() != SpvOpDecorateId) {
|
||||
if (dec->opcode() != spv::Op::OpDecorateId) {
|
||||
continue;
|
||||
}
|
||||
if (dec->GetSingleWordInOperand(1) ==
|
||||
SpvDecorationHlslCounterBufferGOOGLE) {
|
||||
if (spv::Decoration(dec->GetSingleWordInOperand(1)) ==
|
||||
spv::Decoration::HlslCounterBufferGOOGLE) {
|
||||
// These decorations should not force the use id to be live. It will be
|
||||
// removed if either the target or the in operand are dead.
|
||||
continue;
|
||||
@@ -391,7 +392,7 @@ void AggressiveDCEPass::MarkLoadedVariablesAsLive(Function* func,
|
||||
}
|
||||
|
||||
std::vector<uint32_t> AggressiveDCEPass::GetLoadedVariables(Instruction* inst) {
|
||||
if (inst->opcode() == SpvOpFunctionCall) {
|
||||
if (inst->opcode() == spv::Op::OpFunctionCall) {
|
||||
return GetLoadedVariablesFromFunctionCall(inst);
|
||||
}
|
||||
uint32_t var_id = GetLoadedVariableFromNonFunctionCalls(inst);
|
||||
@@ -409,11 +410,11 @@ uint32_t AggressiveDCEPass::GetLoadedVariableFromNonFunctionCalls(
|
||||
}
|
||||
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpLoad:
|
||||
case SpvOpImageTexelPointer:
|
||||
case spv::Op::OpLoad:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
return GetVariableId(inst->GetSingleWordInOperand(kLoadSourceAddrInIdx));
|
||||
case SpvOpCopyMemory:
|
||||
case SpvOpCopyMemorySized:
|
||||
case spv::Op::OpCopyMemory:
|
||||
case spv::Op::OpCopyMemorySized:
|
||||
return GetVariableId(
|
||||
inst->GetSingleWordInOperand(kCopyMemorySourceAddrInIdx));
|
||||
default:
|
||||
@@ -436,7 +437,7 @@ uint32_t AggressiveDCEPass::GetLoadedVariableFromNonFunctionCalls(
|
||||
|
||||
std::vector<uint32_t> AggressiveDCEPass::GetLoadedVariablesFromFunctionCall(
|
||||
const Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpFunctionCall);
|
||||
assert(inst->opcode() == spv::Op::OpFunctionCall);
|
||||
std::vector<uint32_t> live_variables;
|
||||
inst->ForEachInId([this, &live_variables](const uint32_t* operand_id) {
|
||||
if (!IsPtr(*operand_id)) return;
|
||||
@@ -481,7 +482,7 @@ void AggressiveDCEPass::MarkBlockAsLive(Instruction* inst) {
|
||||
// the loop, so the loop construct must be live. We exclude the label because
|
||||
// it does not matter how many times it is executed. This could be extended
|
||||
// to more instructions, but we will need it for now.
|
||||
if (inst->opcode() != SpvOpLabel)
|
||||
if (inst->opcode() != spv::Op::OpLabel)
|
||||
MarkLoopConstructAsLiveIfLoopHeader(basic_block);
|
||||
|
||||
Instruction* next_branch_inst = GetBranchForNextHeader(basic_block);
|
||||
@@ -491,8 +492,8 @@ void AggressiveDCEPass::MarkBlockAsLive(Instruction* inst) {
|
||||
AddToWorklist(mergeInst);
|
||||
}
|
||||
|
||||
if (inst->opcode() == SpvOpLoopMerge ||
|
||||
inst->opcode() == SpvOpSelectionMerge) {
|
||||
if (inst->opcode() == spv::Op::OpLoopMerge ||
|
||||
inst->opcode() == spv::Op::OpSelectionMerge) {
|
||||
AddBreaksAndContinuesToWorklist(inst);
|
||||
}
|
||||
}
|
||||
@@ -529,27 +530,27 @@ void AggressiveDCEPass::InitializeWorkList(
|
||||
// cleaned up.
|
||||
for (auto& bi : structured_order) {
|
||||
for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
|
||||
SpvOp op = ii->opcode();
|
||||
spv::Op op = ii->opcode();
|
||||
if (ii->IsBranch()) {
|
||||
continue;
|
||||
}
|
||||
switch (op) {
|
||||
case SpvOpStore: {
|
||||
case spv::Op::OpStore: {
|
||||
uint32_t var_id = 0;
|
||||
(void)GetPtr(&*ii, &var_id);
|
||||
if (!IsLocalVar(var_id, func)) AddToWorklist(&*ii);
|
||||
} break;
|
||||
case SpvOpCopyMemory:
|
||||
case SpvOpCopyMemorySized: {
|
||||
case spv::Op::OpCopyMemory:
|
||||
case spv::Op::OpCopyMemorySized: {
|
||||
uint32_t var_id = 0;
|
||||
uint32_t target_addr_id =
|
||||
ii->GetSingleWordInOperand(kCopyMemoryTargetAddrInIdx);
|
||||
(void)GetPtr(target_addr_id, &var_id);
|
||||
if (!IsLocalVar(var_id, func)) AddToWorklist(&*ii);
|
||||
} break;
|
||||
case SpvOpLoopMerge:
|
||||
case SpvOpSelectionMerge:
|
||||
case SpvOpUnreachable:
|
||||
case spv::Op::OpLoopMerge:
|
||||
case spv::Op::OpSelectionMerge:
|
||||
case spv::Op::OpUnreachable:
|
||||
break;
|
||||
default: {
|
||||
// Function calls, atomics, function params, function returns, etc.
|
||||
@@ -578,8 +579,10 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
|
||||
auto* var = get_def_use_mgr()->GetDef(entry.GetSingleWordInOperand(i));
|
||||
auto storage_class = var->GetSingleWordInOperand(0u);
|
||||
// Vulkan support outputs without an associated input, but not inputs
|
||||
// without an associated output.
|
||||
if (storage_class == SpvStorageClassOutput) {
|
||||
// without an associated output. Don't remove outputs unless explicitly
|
||||
// allowed.
|
||||
if (!remove_outputs_ &&
|
||||
spv::StorageClass(storage_class) == spv::StorageClass::Output) {
|
||||
AddToWorklist(var);
|
||||
}
|
||||
}
|
||||
@@ -588,24 +591,29 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
|
||||
}
|
||||
}
|
||||
for (auto& anno : get_module()->annotations()) {
|
||||
if (anno.opcode() == SpvOpDecorate) {
|
||||
if (anno.opcode() == spv::Op::OpDecorate) {
|
||||
// Keep workgroup size.
|
||||
if (anno.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn &&
|
||||
anno.GetSingleWordInOperand(2u) == SpvBuiltInWorkgroupSize) {
|
||||
if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::BuiltIn &&
|
||||
spv::BuiltIn(anno.GetSingleWordInOperand(2u)) ==
|
||||
spv::BuiltIn::WorkgroupSize) {
|
||||
AddToWorklist(&anno);
|
||||
}
|
||||
|
||||
if (context()->preserve_bindings()) {
|
||||
// Keep all bindings.
|
||||
if ((anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet) ||
|
||||
(anno.GetSingleWordInOperand(1u) == SpvDecorationBinding)) {
|
||||
if ((spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::DescriptorSet) ||
|
||||
(spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::Binding)) {
|
||||
AddToWorklist(&anno);
|
||||
}
|
||||
}
|
||||
|
||||
if (context()->preserve_spec_constants()) {
|
||||
// Keep all specialization constant instructions
|
||||
if (anno.GetSingleWordInOperand(1u) == SpvDecorationSpecId) {
|
||||
if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::SpecId) {
|
||||
AddToWorklist(&anno);
|
||||
}
|
||||
}
|
||||
@@ -624,7 +632,7 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
|
||||
debug_global_seen = true;
|
||||
dbg.ForEachInId([this](const uint32_t* iid) {
|
||||
Instruction* in_inst = get_def_use_mgr()->GetDef(*iid);
|
||||
if (in_inst->opcode() == SpvOpVariable) return;
|
||||
if (in_inst->opcode() == spv::Op::OpVariable) return;
|
||||
AddToWorklist(in_inst);
|
||||
});
|
||||
}
|
||||
@@ -647,19 +655,19 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
|
||||
Pass::Status AggressiveDCEPass::ProcessImpl() {
|
||||
// Current functionality assumes shader capability
|
||||
// TODO(greg-lunarg): Handle additional capabilities
|
||||
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return Status::SuccessWithoutChange;
|
||||
|
||||
// Current functionality assumes relaxed logical addressing (see
|
||||
// instruction.h)
|
||||
// TODO(greg-lunarg): Handle non-logical addressing
|
||||
if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
|
||||
if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
|
||||
return Status::SuccessWithoutChange;
|
||||
|
||||
// The variable pointer extension is no longer needed to use the capability,
|
||||
// so we have to look for the capability.
|
||||
if (context()->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityVariablePointersStorageBuffer))
|
||||
spv::Capability::VariablePointersStorageBuffer))
|
||||
return Status::SuccessWithoutChange;
|
||||
|
||||
// If any extensions in the module are not explicitly supported,
|
||||
@@ -743,7 +751,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
|
||||
bool modified = false;
|
||||
Instruction* instruction = &*get_module()->debug2_begin();
|
||||
while (instruction) {
|
||||
if (instruction->opcode() != SpvOpName) {
|
||||
if (instruction->opcode() != spv::Op::OpName) {
|
||||
instruction = instruction->NextNode();
|
||||
continue;
|
||||
}
|
||||
@@ -764,22 +772,22 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
|
||||
std::sort(annotations.begin(), annotations.end(), DecorationLess());
|
||||
for (auto annotation : annotations) {
|
||||
switch (annotation->opcode()) {
|
||||
case SpvOpDecorate:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case SpvOpMemberDecorateStringGOOGLE:
|
||||
case spv::Op::OpDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
case spv::Op::OpMemberDecorateStringGOOGLE:
|
||||
if (IsTargetDead(annotation)) {
|
||||
context()->KillInst(annotation);
|
||||
modified = true;
|
||||
}
|
||||
break;
|
||||
case SpvOpDecorateId:
|
||||
case spv::Op::OpDecorateId:
|
||||
if (IsTargetDead(annotation)) {
|
||||
context()->KillInst(annotation);
|
||||
modified = true;
|
||||
} else {
|
||||
if (annotation->GetSingleWordInOperand(1) ==
|
||||
SpvDecorationHlslCounterBufferGOOGLE) {
|
||||
if (spv::Decoration(annotation->GetSingleWordInOperand(1)) ==
|
||||
spv::Decoration::HlslCounterBufferGOOGLE) {
|
||||
// HlslCounterBuffer will reference an id other than the target.
|
||||
// If that id is dead, then the decoration can be removed as well.
|
||||
uint32_t counter_buffer_id = annotation->GetSingleWordInOperand(2);
|
||||
@@ -792,7 +800,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvOpGroupDecorate: {
|
||||
case spv::Op::OpGroupDecorate: {
|
||||
// Go through the targets of this group decorate. Remove each dead
|
||||
// target. If all targets are dead, remove this decoration.
|
||||
bool dead = true;
|
||||
@@ -818,7 +826,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SpvOpGroupMemberDecorate: {
|
||||
case spv::Op::OpGroupMemberDecorate: {
|
||||
// Go through the targets of this group member decorate. Remove each
|
||||
// dead target (and member index). If all targets are dead, remove this
|
||||
// decoration.
|
||||
@@ -846,7 +854,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SpvOpDecorationGroup:
|
||||
case spv::Op::OpDecorationGroup:
|
||||
// By the time we hit decoration groups we've checked everything that
|
||||
// can target them. So if they have no uses they must be dead.
|
||||
if (get_def_use_mgr()->NumUsers(annotation) == 0) {
|
||||
@@ -887,7 +895,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
|
||||
// this live as it does not have a result id. This is a little too
|
||||
// conservative since it is not known if the structure type that needed
|
||||
// it is still live. TODO(greg-lunarg): Only save if needed.
|
||||
if (val.opcode() == SpvOpTypeForwardPointer) {
|
||||
if (val.opcode() == spv::Op::OpTypeForwardPointer) {
|
||||
uint32_t ptr_ty_id = val.GetSingleWordInOperand(0);
|
||||
Instruction* ptr_ty_inst = get_def_use_mgr()->GetDef(ptr_ty_id);
|
||||
if (IsLive(ptr_ty_inst)) continue;
|
||||
@@ -1083,8 +1091,9 @@ bool AggressiveDCEPass::IsEntryPoint(Function* func) {
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::HasCall(Function* func) {
|
||||
return !func->WhileEachInst(
|
||||
[](Instruction* inst) { return inst->opcode() != SpvOpFunctionCall; });
|
||||
return !func->WhileEachInst([](Instruction* inst) {
|
||||
return inst->opcode() != spv::Op::OpFunctionCall;
|
||||
});
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::MarkFirstBlockAsLive(Function* func) {
|
||||
|
||||
@@ -44,8 +44,10 @@ class AggressiveDCEPass : public MemPass {
|
||||
using GetBlocksFunction =
|
||||
std::function<std::vector<BasicBlock*>*(const BasicBlock*)>;
|
||||
|
||||
AggressiveDCEPass(bool preserve_interface = false)
|
||||
: preserve_interface_(preserve_interface) {}
|
||||
AggressiveDCEPass(bool preserve_interface = false,
|
||||
bool remove_outputs = false)
|
||||
: preserve_interface_(preserve_interface),
|
||||
remove_outputs_(remove_outputs) {}
|
||||
|
||||
const char* name() const override { return "eliminate-dead-code-aggressive"; }
|
||||
Status Process() override;
|
||||
@@ -63,9 +65,14 @@ class AggressiveDCEPass : public MemPass {
|
||||
// is not allowed.
|
||||
bool preserve_interface_;
|
||||
|
||||
// Output variables can be removed from the interface if this is true.
|
||||
// This is safe if the caller knows that the corresponding input variable
|
||||
// in the following shader has been removed. It is false by default.
|
||||
bool remove_outputs_;
|
||||
|
||||
// Return true if |varId| is a variable of |storageClass|. |varId| must either
|
||||
// be 0 or the result of an instruction.
|
||||
bool IsVarOfStorage(uint32_t varId, uint32_t storageClass);
|
||||
bool IsVarOfStorage(uint32_t varId, spv::StorageClass storageClass);
|
||||
|
||||
// Return true if the instance of the variable |varId| can only be access in
|
||||
// |func|. For example, a function scope variable, or a private variable
|
||||
|
||||
234
3rdparty/spirv-tools/source/opt/amd_ext_to_khr.cpp
vendored
234
3rdparty/spirv-tools/source/opt/amd_ext_to_khr.cpp
vendored
@@ -24,7 +24,6 @@
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
enum AmdShaderBallotExtOpcodes {
|
||||
@@ -136,19 +135,19 @@ bool ReplaceTrinaryMid(IRContext* ctx, Instruction* inst,
|
||||
// Returns a folding rule that will replace the opcode with |opcode| and add
|
||||
// the capabilities required. The folding rule assumes it is folding an
|
||||
// OpGroup*NonUniformAMD instruction from the SPV_AMD_shader_ballot extension.
|
||||
template <SpvOp new_opcode>
|
||||
template <spv::Op new_opcode>
|
||||
bool ReplaceGroupNonuniformOperationOpCode(
|
||||
IRContext* ctx, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>&) {
|
||||
switch (new_opcode) {
|
||||
case SpvOpGroupNonUniformIAdd:
|
||||
case SpvOpGroupNonUniformFAdd:
|
||||
case SpvOpGroupNonUniformUMin:
|
||||
case SpvOpGroupNonUniformSMin:
|
||||
case SpvOpGroupNonUniformFMin:
|
||||
case SpvOpGroupNonUniformUMax:
|
||||
case SpvOpGroupNonUniformSMax:
|
||||
case SpvOpGroupNonUniformFMax:
|
||||
case spv::Op::OpGroupNonUniformIAdd:
|
||||
case spv::Op::OpGroupNonUniformFAdd:
|
||||
case spv::Op::OpGroupNonUniformUMin:
|
||||
case spv::Op::OpGroupNonUniformSMin:
|
||||
case spv::Op::OpGroupNonUniformFMin:
|
||||
case spv::Op::OpGroupNonUniformUMax:
|
||||
case spv::Op::OpGroupNonUniformSMax:
|
||||
case spv::Op::OpGroupNonUniformFMax:
|
||||
break;
|
||||
default:
|
||||
assert(
|
||||
@@ -157,21 +156,21 @@ bool ReplaceGroupNonuniformOperationOpCode(
|
||||
}
|
||||
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpGroupIAddNonUniformAMD:
|
||||
case SpvOpGroupFAddNonUniformAMD:
|
||||
case SpvOpGroupUMinNonUniformAMD:
|
||||
case SpvOpGroupSMinNonUniformAMD:
|
||||
case SpvOpGroupFMinNonUniformAMD:
|
||||
case SpvOpGroupUMaxNonUniformAMD:
|
||||
case SpvOpGroupSMaxNonUniformAMD:
|
||||
case SpvOpGroupFMaxNonUniformAMD:
|
||||
case spv::Op::OpGroupIAddNonUniformAMD:
|
||||
case spv::Op::OpGroupFAddNonUniformAMD:
|
||||
case spv::Op::OpGroupUMinNonUniformAMD:
|
||||
case spv::Op::OpGroupSMinNonUniformAMD:
|
||||
case spv::Op::OpGroupFMinNonUniformAMD:
|
||||
case spv::Op::OpGroupUMaxNonUniformAMD:
|
||||
case spv::Op::OpGroupSMaxNonUniformAMD:
|
||||
case spv::Op::OpGroupFMaxNonUniformAMD:
|
||||
break;
|
||||
default:
|
||||
assert(false &&
|
||||
"Should be replacing a group non uniform arithmetic operation.");
|
||||
}
|
||||
|
||||
ctx->AddCapability(SpvCapabilityGroupNonUniformArithmetic);
|
||||
ctx->AddCapability(spv::Capability::GroupNonUniformArithmetic);
|
||||
inst->SetOpcode(new_opcode);
|
||||
return true;
|
||||
}
|
||||
@@ -215,8 +214,8 @@ bool ReplaceSwizzleInvocations(IRContext* ctx, Instruction* inst,
|
||||
analysis::ConstantManager* const_mgr = ctx->get_constant_mgr();
|
||||
|
||||
ctx->AddExtension("SPV_KHR_shader_ballot");
|
||||
ctx->AddCapability(SpvCapabilityGroupNonUniformBallot);
|
||||
ctx->AddCapability(SpvCapabilityGroupNonUniformShuffle);
|
||||
ctx->AddCapability(spv::Capability::GroupNonUniformBallot);
|
||||
ctx->AddCapability(spv::Capability::GroupNonUniformShuffle);
|
||||
|
||||
InstructionBuilder ir_builder(
|
||||
ctx, inst,
|
||||
@@ -226,8 +225,8 @@ bool ReplaceSwizzleInvocations(IRContext* ctx, Instruction* inst,
|
||||
uint32_t offset_id = inst->GetSingleWordInOperand(3);
|
||||
|
||||
// Get the subgroup invocation id.
|
||||
uint32_t var_id =
|
||||
ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
|
||||
uint32_t var_id = ctx->GetBuiltinInputVarId(
|
||||
uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
|
||||
assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
|
||||
Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
|
||||
Instruction* var_ptr_type =
|
||||
@@ -239,35 +238,38 @@ bool ReplaceSwizzleInvocations(IRContext* ctx, Instruction* inst,
|
||||
uint32_t quad_mask = ir_builder.GetUintConstantId(3);
|
||||
|
||||
// This gives the offset in the group of 4 of this invocation.
|
||||
Instruction* quad_idx = ir_builder.AddBinaryOp(uint_type_id, SpvOpBitwiseAnd,
|
||||
id->result_id(), quad_mask);
|
||||
Instruction* quad_idx = ir_builder.AddBinaryOp(
|
||||
uint_type_id, spv::Op::OpBitwiseAnd, id->result_id(), quad_mask);
|
||||
|
||||
// Get the invocation id of the first invocation in the group of 4.
|
||||
Instruction* quad_ldr = ir_builder.AddBinaryOp(
|
||||
uint_type_id, SpvOpBitwiseXor, id->result_id(), quad_idx->result_id());
|
||||
Instruction* quad_ldr =
|
||||
ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpBitwiseXor,
|
||||
id->result_id(), quad_idx->result_id());
|
||||
|
||||
// Get the offset of the target invocation from the offset vector.
|
||||
Instruction* my_offset =
|
||||
ir_builder.AddBinaryOp(uint_type_id, SpvOpVectorExtractDynamic, offset_id,
|
||||
quad_idx->result_id());
|
||||
ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpVectorExtractDynamic,
|
||||
offset_id, quad_idx->result_id());
|
||||
|
||||
// Determine the index of the invocation to read from.
|
||||
Instruction* target_inv = ir_builder.AddBinaryOp(
|
||||
uint_type_id, SpvOpIAdd, quad_ldr->result_id(), my_offset->result_id());
|
||||
Instruction* target_inv =
|
||||
ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpIAdd,
|
||||
quad_ldr->result_id(), my_offset->result_id());
|
||||
|
||||
// Do the group operations
|
||||
uint32_t uint_max_id = ir_builder.GetUintConstantId(0xFFFFFFFF);
|
||||
uint32_t subgroup_scope = ir_builder.GetUintConstantId(SpvScopeSubgroup);
|
||||
uint32_t subgroup_scope =
|
||||
ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
|
||||
const auto* ballot_value_const = const_mgr->GetConstant(
|
||||
type_mgr->GetUIntVectorType(4),
|
||||
{uint_max_id, uint_max_id, uint_max_id, uint_max_id});
|
||||
Instruction* ballot_value =
|
||||
const_mgr->GetDefiningInstruction(ballot_value_const);
|
||||
Instruction* is_active = ir_builder.AddNaryOp(
|
||||
type_mgr->GetBoolTypeId(), SpvOpGroupNonUniformBallotBitExtract,
|
||||
type_mgr->GetBoolTypeId(), spv::Op::OpGroupNonUniformBallotBitExtract,
|
||||
{subgroup_scope, ballot_value->result_id(), target_inv->result_id()});
|
||||
Instruction* shuffle =
|
||||
ir_builder.AddNaryOp(inst->type_id(), SpvOpGroupNonUniformShuffle,
|
||||
ir_builder.AddNaryOp(inst->type_id(), spv::Op::OpGroupNonUniformShuffle,
|
||||
{subgroup_scope, data_id, target_inv->result_id()});
|
||||
|
||||
// Create the null constant to use in the select.
|
||||
@@ -276,7 +278,7 @@ bool ReplaceSwizzleInvocations(IRContext* ctx, Instruction* inst,
|
||||
Instruction* null_inst = const_mgr->GetDefiningInstruction(null);
|
||||
|
||||
// Build the select.
|
||||
inst->SetOpcode(SpvOpSelect);
|
||||
inst->SetOpcode(spv::Op::OpSelect);
|
||||
Instruction::OperandList new_operands;
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_active->result_id()}});
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {shuffle->result_id()}});
|
||||
@@ -327,8 +329,8 @@ bool ReplaceSwizzleInvocationsMasked(
|
||||
analysis::DefUseManager* def_use_mgr = ctx->get_def_use_mgr();
|
||||
analysis::ConstantManager* const_mgr = ctx->get_constant_mgr();
|
||||
|
||||
ctx->AddCapability(SpvCapabilityGroupNonUniformBallot);
|
||||
ctx->AddCapability(SpvCapabilityGroupNonUniformShuffle);
|
||||
ctx->AddCapability(spv::Capability::GroupNonUniformBallot);
|
||||
ctx->AddCapability(spv::Capability::GroupNonUniformShuffle);
|
||||
|
||||
InstructionBuilder ir_builder(
|
||||
ctx, inst,
|
||||
@@ -338,7 +340,7 @@ bool ReplaceSwizzleInvocationsMasked(
|
||||
uint32_t data_id = inst->GetSingleWordInOperand(2);
|
||||
|
||||
Instruction* mask_inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(3));
|
||||
assert(mask_inst->opcode() == SpvOpConstantComposite &&
|
||||
assert(mask_inst->opcode() == spv::Op::OpConstantComposite &&
|
||||
"The mask is suppose to be a vector constant.");
|
||||
assert(mask_inst->NumInOperands() == 3 &&
|
||||
"The mask is suppose to have 3 components.");
|
||||
@@ -348,8 +350,8 @@ bool ReplaceSwizzleInvocationsMasked(
|
||||
uint32_t uint_z = mask_inst->GetSingleWordInOperand(2);
|
||||
|
||||
// Get the subgroup invocation id.
|
||||
uint32_t var_id =
|
||||
ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
|
||||
uint32_t var_id = ctx->GetBuiltinInputVarId(
|
||||
uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
|
||||
ctx->AddExtension("SPV_KHR_shader_ballot");
|
||||
assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
|
||||
Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
|
||||
@@ -361,28 +363,30 @@ bool ReplaceSwizzleInvocationsMasked(
|
||||
|
||||
// Do the bitwise operations.
|
||||
uint32_t mask_extended = ir_builder.GetUintConstantId(0xFFFFFFE0);
|
||||
Instruction* and_mask = ir_builder.AddBinaryOp(uint_type_id, SpvOpBitwiseOr,
|
||||
uint_x, mask_extended);
|
||||
Instruction* and_result = ir_builder.AddBinaryOp(
|
||||
uint_type_id, SpvOpBitwiseAnd, id->result_id(), and_mask->result_id());
|
||||
Instruction* and_mask = ir_builder.AddBinaryOp(
|
||||
uint_type_id, spv::Op::OpBitwiseOr, uint_x, mask_extended);
|
||||
Instruction* and_result =
|
||||
ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpBitwiseAnd,
|
||||
id->result_id(), and_mask->result_id());
|
||||
Instruction* or_result = ir_builder.AddBinaryOp(
|
||||
uint_type_id, SpvOpBitwiseOr, and_result->result_id(), uint_y);
|
||||
uint_type_id, spv::Op::OpBitwiseOr, and_result->result_id(), uint_y);
|
||||
Instruction* target_inv = ir_builder.AddBinaryOp(
|
||||
uint_type_id, SpvOpBitwiseXor, or_result->result_id(), uint_z);
|
||||
uint_type_id, spv::Op::OpBitwiseXor, or_result->result_id(), uint_z);
|
||||
|
||||
// Do the group operations
|
||||
uint32_t uint_max_id = ir_builder.GetUintConstantId(0xFFFFFFFF);
|
||||
uint32_t subgroup_scope = ir_builder.GetUintConstantId(SpvScopeSubgroup);
|
||||
uint32_t subgroup_scope =
|
||||
ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
|
||||
const auto* ballot_value_const = const_mgr->GetConstant(
|
||||
type_mgr->GetUIntVectorType(4),
|
||||
{uint_max_id, uint_max_id, uint_max_id, uint_max_id});
|
||||
Instruction* ballot_value =
|
||||
const_mgr->GetDefiningInstruction(ballot_value_const);
|
||||
Instruction* is_active = ir_builder.AddNaryOp(
|
||||
type_mgr->GetBoolTypeId(), SpvOpGroupNonUniformBallotBitExtract,
|
||||
type_mgr->GetBoolTypeId(), spv::Op::OpGroupNonUniformBallotBitExtract,
|
||||
{subgroup_scope, ballot_value->result_id(), target_inv->result_id()});
|
||||
Instruction* shuffle =
|
||||
ir_builder.AddNaryOp(inst->type_id(), SpvOpGroupNonUniformShuffle,
|
||||
ir_builder.AddNaryOp(inst->type_id(), spv::Op::OpGroupNonUniformShuffle,
|
||||
{subgroup_scope, data_id, target_inv->result_id()});
|
||||
|
||||
// Create the null constant to use in the select.
|
||||
@@ -391,7 +395,7 @@ bool ReplaceSwizzleInvocationsMasked(
|
||||
Instruction* null_inst = const_mgr->GetDefiningInstruction(null);
|
||||
|
||||
// Build the select.
|
||||
inst->SetOpcode(SpvOpSelect);
|
||||
inst->SetOpcode(spv::Op::OpSelect);
|
||||
Instruction::OperandList new_operands;
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_active->result_id()}});
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {shuffle->result_id()}});
|
||||
@@ -420,9 +424,9 @@ bool ReplaceSwizzleInvocationsMasked(
|
||||
// Also adding the capabilities and builtins that are needed.
|
||||
bool ReplaceWriteInvocation(IRContext* ctx, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>&) {
|
||||
uint32_t var_id =
|
||||
ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
|
||||
ctx->AddCapability(SpvCapabilitySubgroupBallotKHR);
|
||||
uint32_t var_id = ctx->GetBuiltinInputVarId(
|
||||
uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
|
||||
ctx->AddCapability(spv::Capability::SubgroupBallotKHR);
|
||||
ctx->AddExtension("SPV_KHR_shader_ballot");
|
||||
assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
|
||||
Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
|
||||
@@ -437,11 +441,11 @@ bool ReplaceWriteInvocation(IRContext* ctx, Instruction* inst,
|
||||
analysis::Bool bool_type;
|
||||
uint32_t bool_type_id = ctx->get_type_mgr()->GetTypeInstruction(&bool_type);
|
||||
Instruction* cmp =
|
||||
ir_builder.AddBinaryOp(bool_type_id, SpvOpIEqual, t->result_id(),
|
||||
ir_builder.AddBinaryOp(bool_type_id, spv::Op::OpIEqual, t->result_id(),
|
||||
inst->GetSingleWordInOperand(4));
|
||||
|
||||
// Build a select.
|
||||
inst->SetOpcode(SpvOpSelect);
|
||||
inst->SetOpcode(spv::Op::OpSelect);
|
||||
Instruction::OperandList new_operands;
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {cmp->result_id()}});
|
||||
new_operands.push_back(inst->GetInOperand(3));
|
||||
@@ -479,14 +483,15 @@ bool ReplaceMbcnt(IRContext* context, Instruction* inst,
|
||||
analysis::TypeManager* type_mgr = context->get_type_mgr();
|
||||
analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
|
||||
|
||||
uint32_t var_id = context->GetBuiltinInputVarId(SpvBuiltInSubgroupLtMask);
|
||||
uint32_t var_id =
|
||||
context->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::SubgroupLtMask));
|
||||
assert(var_id != 0 && "Could not get SubgroupLtMask variable.");
|
||||
context->AddCapability(SpvCapabilityGroupNonUniformBallot);
|
||||
context->AddCapability(spv::Capability::GroupNonUniformBallot);
|
||||
Instruction* var_inst = def_use_mgr->GetDef(var_id);
|
||||
Instruction* var_ptr_type = def_use_mgr->GetDef(var_inst->type_id());
|
||||
Instruction* var_type =
|
||||
def_use_mgr->GetDef(var_ptr_type->GetSingleWordInOperand(1));
|
||||
assert(var_type->opcode() == SpvOpTypeVector &&
|
||||
assert(var_type->opcode() == spv::Op::OpTypeVector &&
|
||||
"Variable is suppose to be a vector of 4 ints");
|
||||
|
||||
// Get the type for the shuffle.
|
||||
@@ -509,11 +514,12 @@ bool ReplaceMbcnt(IRContext* context, Instruction* inst,
|
||||
Instruction* shuffle = ir_builder.AddVectorShuffle(
|
||||
shuffle_type_id, load->result_id(), load->result_id(), {0, 1});
|
||||
Instruction* bitcast = ir_builder.AddUnaryOp(
|
||||
mask_inst->type_id(), SpvOpBitcast, shuffle->result_id());
|
||||
Instruction* t = ir_builder.AddBinaryOp(mask_inst->type_id(), SpvOpBitwiseAnd,
|
||||
bitcast->result_id(), mask_id);
|
||||
mask_inst->type_id(), spv::Op::OpBitcast, shuffle->result_id());
|
||||
Instruction* t =
|
||||
ir_builder.AddBinaryOp(mask_inst->type_id(), spv::Op::OpBitwiseAnd,
|
||||
bitcast->result_id(), mask_id);
|
||||
|
||||
inst->SetOpcode(SpvOpBitCount);
|
||||
inst->SetOpcode(spv::Op::OpBitCount);
|
||||
inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {t->result_id()}}});
|
||||
context->UpdateDefUse(inst);
|
||||
return true;
|
||||
@@ -599,11 +605,11 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst,
|
||||
|
||||
// Negate the input values.
|
||||
Instruction* nx =
|
||||
ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, x->result_id());
|
||||
ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, x->result_id());
|
||||
Instruction* ny =
|
||||
ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, y->result_id());
|
||||
ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, y->result_id());
|
||||
Instruction* nz =
|
||||
ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, z->result_id());
|
||||
ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, z->result_id());
|
||||
|
||||
// Get the abolsute values of the inputs.
|
||||
Instruction* ax = ir_builder.AddNaryExtendedInstruction(
|
||||
@@ -614,12 +620,12 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst,
|
||||
float_type_id, glsl405_ext_inst_id, GLSLstd450FAbs, {z->result_id()});
|
||||
|
||||
// Find which values are negative. Used in later computations.
|
||||
Instruction* is_z_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
|
||||
z->result_id(), f0_const_id);
|
||||
Instruction* is_y_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
|
||||
y->result_id(), f0_const_id);
|
||||
Instruction* is_x_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
|
||||
x->result_id(), f0_const_id);
|
||||
Instruction* is_z_neg = ir_builder.AddBinaryOp(
|
||||
bool_id, spv::Op::OpFOrdLessThan, z->result_id(), f0_const_id);
|
||||
Instruction* is_y_neg = ir_builder.AddBinaryOp(
|
||||
bool_id, spv::Op::OpFOrdLessThan, y->result_id(), f0_const_id);
|
||||
Instruction* is_x_neg = ir_builder.AddBinaryOp(
|
||||
bool_id, spv::Op::OpFOrdLessThan, x->result_id(), f0_const_id);
|
||||
|
||||
// Compute cubema
|
||||
Instruction* amax_x_y = ir_builder.AddNaryExtendedInstruction(
|
||||
@@ -628,19 +634,21 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst,
|
||||
Instruction* amax = ir_builder.AddNaryExtendedInstruction(
|
||||
float_type_id, glsl405_ext_inst_id, GLSLstd450FMax,
|
||||
{az->result_id(), amax_x_y->result_id()});
|
||||
Instruction* cubema = ir_builder.AddBinaryOp(float_type_id, SpvOpFMul,
|
||||
Instruction* cubema = ir_builder.AddBinaryOp(float_type_id, spv::Op::OpFMul,
|
||||
f2_const_id, amax->result_id());
|
||||
|
||||
// Do the comparisons needed for computing cubesc and cubetc.
|
||||
Instruction* is_z_max =
|
||||
ir_builder.AddBinaryOp(bool_id, SpvOpFOrdGreaterThanEqual,
|
||||
ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
|
||||
az->result_id(), amax_x_y->result_id());
|
||||
Instruction* not_is_z_max =
|
||||
ir_builder.AddUnaryOp(bool_id, SpvOpLogicalNot, is_z_max->result_id());
|
||||
Instruction* y_gr_x = ir_builder.AddBinaryOp(
|
||||
bool_id, SpvOpFOrdGreaterThanEqual, ay->result_id(), ax->result_id());
|
||||
Instruction* is_y_max = ir_builder.AddBinaryOp(
|
||||
bool_id, SpvOpLogicalAnd, not_is_z_max->result_id(), y_gr_x->result_id());
|
||||
Instruction* not_is_z_max = ir_builder.AddUnaryOp(
|
||||
bool_id, spv::Op::OpLogicalNot, is_z_max->result_id());
|
||||
Instruction* y_gr_x =
|
||||
ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
|
||||
ay->result_id(), ax->result_id());
|
||||
Instruction* is_y_max =
|
||||
ir_builder.AddBinaryOp(bool_id, spv::Op::OpLogicalAnd,
|
||||
not_is_z_max->result_id(), y_gr_x->result_id());
|
||||
|
||||
// Select the correct value for cubesc.
|
||||
Instruction* cubesc_case_1 = ir_builder.AddSelect(
|
||||
@@ -667,10 +675,10 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst,
|
||||
Instruction* denom = ir_builder.AddCompositeConstruct(
|
||||
v2_float_type_id, {cubema->result_id(), cubema->result_id()});
|
||||
Instruction* div = ir_builder.AddBinaryOp(
|
||||
v2_float_type_id, SpvOpFDiv, cube->result_id(), denom->result_id());
|
||||
v2_float_type_id, spv::Op::OpFDiv, cube->result_id(), denom->result_id());
|
||||
|
||||
// Get the final result by adding 0.5 to |div|.
|
||||
inst->SetOpcode(SpvOpFAdd);
|
||||
inst->SetOpcode(spv::Op::OpFAdd);
|
||||
Instruction::OperandList new_operands;
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {div->result_id()}});
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {vec_const_id}});
|
||||
@@ -752,22 +760,23 @@ bool ReplaceCubeFaceIndex(IRContext* ctx, Instruction* inst,
|
||||
float_type_id, glsl405_ext_inst_id, GLSLstd450FAbs, {z->result_id()});
|
||||
|
||||
// Find which values are negative. Used in later computations.
|
||||
Instruction* is_z_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
|
||||
z->result_id(), f0_const_id);
|
||||
Instruction* is_y_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
|
||||
y->result_id(), f0_const_id);
|
||||
Instruction* is_x_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
|
||||
x->result_id(), f0_const_id);
|
||||
Instruction* is_z_neg = ir_builder.AddBinaryOp(
|
||||
bool_id, spv::Op::OpFOrdLessThan, z->result_id(), f0_const_id);
|
||||
Instruction* is_y_neg = ir_builder.AddBinaryOp(
|
||||
bool_id, spv::Op::OpFOrdLessThan, y->result_id(), f0_const_id);
|
||||
Instruction* is_x_neg = ir_builder.AddBinaryOp(
|
||||
bool_id, spv::Op::OpFOrdLessThan, x->result_id(), f0_const_id);
|
||||
|
||||
// Find the max value.
|
||||
Instruction* amax_x_y = ir_builder.AddNaryExtendedInstruction(
|
||||
float_type_id, glsl405_ext_inst_id, GLSLstd450FMax,
|
||||
{ax->result_id(), ay->result_id()});
|
||||
Instruction* is_z_max =
|
||||
ir_builder.AddBinaryOp(bool_id, SpvOpFOrdGreaterThanEqual,
|
||||
ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
|
||||
az->result_id(), amax_x_y->result_id());
|
||||
Instruction* y_gr_x = ir_builder.AddBinaryOp(
|
||||
bool_id, SpvOpFOrdGreaterThanEqual, ay->result_id(), ax->result_id());
|
||||
Instruction* y_gr_x =
|
||||
ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
|
||||
ay->result_id(), ax->result_id());
|
||||
|
||||
// Get the value for each case.
|
||||
Instruction* case_z = ir_builder.AddSelect(
|
||||
@@ -783,7 +792,7 @@ bool ReplaceCubeFaceIndex(IRContext* ctx, Instruction* inst,
|
||||
case_y->result_id(), case_x->result_id());
|
||||
|
||||
// Get the final result by adding 0.5 to |div|.
|
||||
inst->SetOpcode(SpvOpSelect);
|
||||
inst->SetOpcode(spv::Op::OpSelect);
|
||||
Instruction::OperandList new_operands;
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_z_max->result_id()}});
|
||||
new_operands.push_back({SPV_OPERAND_TYPE_ID, {case_z->result_id()}});
|
||||
@@ -813,11 +822,12 @@ bool ReplaceTimeAMD(IRContext* ctx, Instruction* inst,
|
||||
ctx, inst,
|
||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
||||
ctx->AddExtension("SPV_KHR_shader_clock");
|
||||
ctx->AddCapability(SpvCapabilityShaderClockKHR);
|
||||
ctx->AddCapability(spv::Capability::ShaderClockKHR);
|
||||
|
||||
inst->SetOpcode(SpvOpReadClockKHR);
|
||||
inst->SetOpcode(spv::Op::OpReadClockKHR);
|
||||
Instruction::OperandList args;
|
||||
uint32_t subgroup_scope_id = ir_builder.GetUintConstantId(SpvScopeSubgroup);
|
||||
uint32_t subgroup_scope_id =
|
||||
ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
|
||||
args.push_back({SPV_OPERAND_TYPE_ID, {subgroup_scope_id}});
|
||||
inst->SetInOperands(std::move(args));
|
||||
ctx->UpdateDefUse(inst);
|
||||
@@ -831,22 +841,22 @@ class AmdExtFoldingRules : public FoldingRules {
|
||||
|
||||
protected:
|
||||
virtual void AddFoldingRules() override {
|
||||
rules_[SpvOpGroupIAddNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformIAdd>);
|
||||
rules_[SpvOpGroupFAddNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFAdd>);
|
||||
rules_[SpvOpGroupUMinNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformUMin>);
|
||||
rules_[SpvOpGroupSMinNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformSMin>);
|
||||
rules_[SpvOpGroupFMinNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFMin>);
|
||||
rules_[SpvOpGroupUMaxNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformUMax>);
|
||||
rules_[SpvOpGroupSMaxNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformSMax>);
|
||||
rules_[SpvOpGroupFMaxNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFMax>);
|
||||
rules_[spv::Op::OpGroupIAddNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformIAdd>);
|
||||
rules_[spv::Op::OpGroupFAddNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFAdd>);
|
||||
rules_[spv::Op::OpGroupUMinNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformUMin>);
|
||||
rules_[spv::Op::OpGroupSMinNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformSMin>);
|
||||
rules_[spv::Op::OpGroupFMinNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFMin>);
|
||||
rules_[spv::Op::OpGroupUMaxNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformUMax>);
|
||||
rules_[spv::Op::OpGroupSMaxNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformSMax>);
|
||||
rules_[spv::Op::OpGroupFMaxNonUniformAMD].push_back(
|
||||
ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFMax>);
|
||||
|
||||
uint32_t extension_id =
|
||||
context()->module()->GetExtInstImportId("SPV_AMD_shader_ballot");
|
||||
@@ -934,7 +944,7 @@ Pass::Status AmdExtensionToKhrPass::Process() {
|
||||
|
||||
std::vector<Instruction*> to_be_killed;
|
||||
for (Instruction& inst : context()->module()->extensions()) {
|
||||
if (inst.opcode() == SpvOpExtension) {
|
||||
if (inst.opcode() == spv::Op::OpExtension) {
|
||||
if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
|
||||
to_be_killed.push_back(&inst);
|
||||
}
|
||||
@@ -942,7 +952,7 @@ Pass::Status AmdExtensionToKhrPass::Process() {
|
||||
}
|
||||
|
||||
for (Instruction& inst : context()->ext_inst_imports()) {
|
||||
if (inst.opcode() == SpvOpExtInstImport) {
|
||||
if (inst.opcode() == spv::Op::OpExtInstImport) {
|
||||
if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
|
||||
to_be_killed.push_back(&inst);
|
||||
}
|
||||
|
||||
45
3rdparty/spirv-tools/source/opt/analyze_live_input_pass.cpp
vendored
Normal file
45
3rdparty/spirv-tools/source/opt/analyze_live_input_pass.cpp
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2022 The Khronos Group Inc.
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/opt/analyze_live_input_pass.h"
|
||||
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
Pass::Status AnalyzeLiveInputPass::Process() {
|
||||
// Current functionality assumes shader capability
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return Status::SuccessWithoutChange;
|
||||
Pass::Status status = DoLiveInputAnalysis();
|
||||
return status;
|
||||
}
|
||||
|
||||
Pass::Status AnalyzeLiveInputPass::DoLiveInputAnalysis() {
|
||||
// Current functionality only supports frag, tesc, tese or geom shaders.
|
||||
// Report failure for any other stage.
|
||||
auto stage = context()->GetStage();
|
||||
if (stage != spv::ExecutionModel::Fragment &&
|
||||
stage != spv::ExecutionModel::TessellationControl &&
|
||||
stage != spv::ExecutionModel::TessellationEvaluation &&
|
||||
stage != spv::ExecutionModel::Geometry)
|
||||
return Status::Failure;
|
||||
context()->get_liveness_mgr()->GetLiveness(live_locs_, live_builtins_);
|
||||
return Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
57
3rdparty/spirv-tools/source/opt/analyze_live_input_pass.h
vendored
Normal file
57
3rdparty/spirv-tools/source/opt/analyze_live_input_pass.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2022 The Khronos Group Inc.
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
|
||||
#define SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "source/opt/pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// See optimizer.hpp for documentation.
|
||||
class AnalyzeLiveInputPass : public Pass {
|
||||
public:
|
||||
explicit AnalyzeLiveInputPass(std::unordered_set<uint32_t>* live_locs,
|
||||
std::unordered_set<uint32_t>* live_builtins)
|
||||
: live_locs_(live_locs), live_builtins_(live_builtins) {}
|
||||
|
||||
const char* name() const override { return "analyze-live-input"; }
|
||||
Status Process() override;
|
||||
|
||||
// Return the mask of preserved Analyses.
|
||||
IRContext::Analysis GetPreservedAnalyses() override {
|
||||
return IRContext::kAnalysisDefUse |
|
||||
IRContext::kAnalysisInstrToBlockMapping |
|
||||
IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG |
|
||||
IRContext::kAnalysisDominatorAnalysis |
|
||||
IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
|
||||
IRContext::kAnalysisConstants | IRContext::kAnalysisTypes;
|
||||
}
|
||||
|
||||
private:
|
||||
// Do live input analysis
|
||||
Status DoLiveInputAnalysis();
|
||||
|
||||
std::unordered_set<uint32_t>* live_locs_;
|
||||
std::unordered_set<uint32_t>* live_builtins_;
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_OPT_ANALYZE_LIVE_INPUT_H_
|
||||
45
3rdparty/spirv-tools/source/opt/basic_block.cpp
vendored
45
3rdparty/spirv-tools/source/opt/basic_block.cpp
vendored
@@ -25,11 +25,9 @@
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
|
||||
const uint32_t kLoopMergeContinueBlockIdInIdx = 1;
|
||||
const uint32_t kLoopMergeMergeBlockIdInIdx = 0;
|
||||
const uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
|
||||
|
||||
constexpr uint32_t kLoopMergeContinueBlockIdInIdx = 1;
|
||||
constexpr uint32_t kLoopMergeMergeBlockIdInIdx = 0;
|
||||
constexpr uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
|
||||
} // namespace
|
||||
|
||||
BasicBlock* BasicBlock::Clone(IRContext* context) const {
|
||||
@@ -58,7 +56,7 @@ const Instruction* BasicBlock::GetMergeInst() const {
|
||||
if (iter != cbegin()) {
|
||||
--iter;
|
||||
const auto opcode = iter->opcode();
|
||||
if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
|
||||
if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge) {
|
||||
result = &*iter;
|
||||
}
|
||||
}
|
||||
@@ -73,7 +71,7 @@ Instruction* BasicBlock::GetMergeInst() {
|
||||
if (iter != begin()) {
|
||||
--iter;
|
||||
const auto opcode = iter->opcode();
|
||||
if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
|
||||
if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge) {
|
||||
result = &*iter;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +80,7 @@ Instruction* BasicBlock::GetMergeInst() {
|
||||
|
||||
const Instruction* BasicBlock::GetLoopMergeInst() const {
|
||||
if (auto* merge = GetMergeInst()) {
|
||||
if (merge->opcode() == SpvOpLoopMerge) {
|
||||
if (merge->opcode() == spv::Op::OpLoopMerge) {
|
||||
return merge;
|
||||
}
|
||||
}
|
||||
@@ -91,7 +89,7 @@ const Instruction* BasicBlock::GetLoopMergeInst() const {
|
||||
|
||||
Instruction* BasicBlock::GetLoopMergeInst() {
|
||||
if (auto* merge = GetMergeInst()) {
|
||||
if (merge->opcode() == SpvOpLoopMerge) {
|
||||
if (merge->opcode() == spv::Op::OpLoopMerge) {
|
||||
return merge;
|
||||
}
|
||||
}
|
||||
@@ -100,7 +98,7 @@ Instruction* BasicBlock::GetLoopMergeInst() {
|
||||
|
||||
void BasicBlock::KillAllInsts(bool killLabel) {
|
||||
ForEachInst([killLabel](Instruction* ip) {
|
||||
if (killLabel || ip->opcode() != SpvOpLabel) {
|
||||
if (killLabel || ip->opcode() != spv::Op::OpLabel) {
|
||||
ip->context()->KillInst(ip);
|
||||
}
|
||||
});
|
||||
@@ -118,10 +116,10 @@ bool BasicBlock::WhileEachSuccessorLabel(
|
||||
const std::function<bool(const uint32_t)>& f) const {
|
||||
const auto br = &insts_.back();
|
||||
switch (br->opcode()) {
|
||||
case SpvOpBranch:
|
||||
case spv::Op::OpBranch:
|
||||
return f(br->GetOperand(0).words[0]);
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch: {
|
||||
case spv::Op::OpBranchConditional:
|
||||
case spv::Op::OpSwitch: {
|
||||
bool is_first = true;
|
||||
return br->WhileEachInId([&is_first, &f](const uint32_t* idp) {
|
||||
if (!is_first) return f(*idp);
|
||||
@@ -138,13 +136,13 @@ void BasicBlock::ForEachSuccessorLabel(
|
||||
const std::function<void(uint32_t*)>& f) {
|
||||
auto br = &insts_.back();
|
||||
switch (br->opcode()) {
|
||||
case SpvOpBranch: {
|
||||
case spv::Op::OpBranch: {
|
||||
uint32_t tmp_id = br->GetOperand(0).words[0];
|
||||
f(&tmp_id);
|
||||
if (tmp_id != br->GetOperand(0).words[0]) br->SetOperand(0, {tmp_id});
|
||||
} break;
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch: {
|
||||
case spv::Op::OpBranchConditional:
|
||||
case spv::Op::OpSwitch: {
|
||||
bool is_first = true;
|
||||
br->ForEachInId([&is_first, &f](uint32_t* idp) {
|
||||
if (!is_first) f(idp);
|
||||
@@ -171,7 +169,8 @@ void BasicBlock::ForMergeAndContinueLabel(
|
||||
--ii;
|
||||
if (ii == insts_.begin()) return;
|
||||
--ii;
|
||||
if (ii->opcode() == SpvOpSelectionMerge || ii->opcode() == SpvOpLoopMerge) {
|
||||
if (ii->opcode() == spv::Op::OpSelectionMerge ||
|
||||
ii->opcode() == spv::Op::OpLoopMerge) {
|
||||
ii->ForEachInId([&f](const uint32_t* idp) { f(*idp); });
|
||||
}
|
||||
}
|
||||
@@ -182,9 +181,9 @@ uint32_t BasicBlock::MergeBlockIdIfAny() const {
|
||||
uint32_t mbid = 0;
|
||||
if (merge_ii != cbegin()) {
|
||||
--merge_ii;
|
||||
if (merge_ii->opcode() == SpvOpLoopMerge) {
|
||||
if (merge_ii->opcode() == spv::Op::OpLoopMerge) {
|
||||
mbid = merge_ii->GetSingleWordInOperand(kLoopMergeMergeBlockIdInIdx);
|
||||
} else if (merge_ii->opcode() == SpvOpSelectionMerge) {
|
||||
} else if (merge_ii->opcode() == spv::Op::OpSelectionMerge) {
|
||||
mbid = merge_ii->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
|
||||
}
|
||||
}
|
||||
@@ -204,7 +203,7 @@ uint32_t BasicBlock::ContinueBlockIdIfAny() const {
|
||||
uint32_t cbid = 0;
|
||||
if (merge_ii != cbegin()) {
|
||||
--merge_ii;
|
||||
if (merge_ii->opcode() == SpvOpLoopMerge) {
|
||||
if (merge_ii->opcode() == spv::Op::OpLoopMerge) {
|
||||
cbid = merge_ii->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
|
||||
}
|
||||
}
|
||||
@@ -241,9 +240,9 @@ BasicBlock* BasicBlock::SplitBasicBlock(IRContext* context, uint32_t label_id,
|
||||
iterator iter) {
|
||||
assert(!insts_.empty());
|
||||
|
||||
std::unique_ptr<BasicBlock> new_block_temp =
|
||||
MakeUnique<BasicBlock>(MakeUnique<Instruction>(
|
||||
context, SpvOpLabel, 0, label_id, std::initializer_list<Operand>{}));
|
||||
std::unique_ptr<BasicBlock> new_block_temp = MakeUnique<BasicBlock>(
|
||||
MakeUnique<Instruction>(context, spv::Op::OpLabel, 0, label_id,
|
||||
std::initializer_list<Operand>{}));
|
||||
BasicBlock* new_block = new_block_temp.get();
|
||||
function_->InsertBasicBlockAfter(std::move(new_block_temp), this);
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ inline bool BasicBlock::WhileEachPhiInst(
|
||||
Instruction* inst = &insts_.front();
|
||||
while (inst != nullptr) {
|
||||
Instruction* next_instruction = inst->NextNode();
|
||||
if (inst->opcode() != SpvOpPhi) break;
|
||||
if (inst->opcode() != spv::Op::OpPhi) break;
|
||||
if (!inst->WhileEachInst(f, run_on_debug_line_insts)) return false;
|
||||
inst = next_instruction;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace blockmergeutil {
|
||||
|
||||
namespace {
|
||||
|
||||
// Returns true if |block| contains a merge instruction.
|
||||
@@ -34,14 +33,15 @@ bool IsHeader(IRContext* context, uint32_t id) {
|
||||
|
||||
// Returns true if |id| is the merge target of a merge instruction.
|
||||
bool IsMerge(IRContext* context, uint32_t id) {
|
||||
return !context->get_def_use_mgr()->WhileEachUse(id, [](Instruction* user,
|
||||
uint32_t index) {
|
||||
SpvOp op = user->opcode();
|
||||
if ((op == SpvOpLoopMerge || op == SpvOpSelectionMerge) && index == 0u) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return !context->get_def_use_mgr()->WhileEachUse(
|
||||
id, [](Instruction* user, uint32_t index) {
|
||||
spv::Op op = user->opcode();
|
||||
if ((op == spv::Op::OpLoopMerge || op == spv::Op::OpSelectionMerge) &&
|
||||
index == 0u) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
// Returns true if |block| is the merge target of a merge instruction.
|
||||
@@ -53,8 +53,8 @@ bool IsMerge(IRContext* context, BasicBlock* block) {
|
||||
bool IsContinue(IRContext* context, uint32_t id) {
|
||||
return !context->get_def_use_mgr()->WhileEachUse(
|
||||
id, [](Instruction* user, uint32_t index) {
|
||||
SpvOp op = user->opcode();
|
||||
if (op == SpvOpLoopMerge && index == 1u) {
|
||||
spv::Op op = user->opcode();
|
||||
if (op == spv::Op::OpLoopMerge && index == 1u) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -82,7 +82,7 @@ bool CanMergeWithSuccessor(IRContext* context, BasicBlock* block) {
|
||||
auto ii = block->end();
|
||||
--ii;
|
||||
Instruction* br = &*ii;
|
||||
if (br->opcode() != SpvOpBranch) {
|
||||
if (br->opcode() != spv::Op::OpBranch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -119,9 +119,10 @@ bool CanMergeWithSuccessor(IRContext* context, BasicBlock* block) {
|
||||
// The merge must be a loop merge because a selection merge cannot be
|
||||
// followed by an unconditional branch.
|
||||
BasicBlock* succ_block = context->get_instr_block(lab_id);
|
||||
SpvOp succ_term_op = succ_block->terminator()->opcode();
|
||||
assert(merge_inst->opcode() == SpvOpLoopMerge);
|
||||
if (succ_term_op != SpvOpBranch && succ_term_op != SpvOpBranchConditional) {
|
||||
spv::Op succ_term_op = succ_block->terminator()->opcode();
|
||||
assert(merge_inst->opcode() == spv::Op::OpLoopMerge);
|
||||
if (succ_term_op != spv::Op::OpBranch &&
|
||||
succ_term_op != spv::Op::OpBranchConditional) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -170,6 +171,11 @@ void MergeWithSuccessor(IRContext* context, Function* func,
|
||||
// sbi must follow bi in func's ordering.
|
||||
assert(sbi != func->end());
|
||||
|
||||
if (sbi->tail()->opcode() == spv::Op::OpSwitch &&
|
||||
sbi->MergeBlockIdIfAny() != 0) {
|
||||
context->InvalidateAnalyses(IRContext::Analysis::kAnalysisStructuredCFG);
|
||||
}
|
||||
|
||||
// Update the inst-to-block mapping for the instructions in sbi.
|
||||
for (auto& inst : *sbi) {
|
||||
context->set_instr_block(&inst, &*bi);
|
||||
|
||||
15
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
15
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
@@ -29,14 +29,11 @@
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
// This SSA id is never defined nor referenced in the IR. It is a special ID
|
||||
// which represents varying values. When an ID is found to have a varying
|
||||
// value, its entry in the |values_| table maps to kVaryingSSAId.
|
||||
const uint32_t kVaryingSSAId = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
constexpr uint32_t kVaryingSSAId = std::numeric_limits<uint32_t>::max();
|
||||
} // namespace
|
||||
|
||||
bool CCPPass::IsVaryingValue(uint32_t id) const { return id == kVaryingSSAId; }
|
||||
@@ -136,7 +133,7 @@ SSAPropagator::PropStatus CCPPass::VisitAssignment(Instruction* instr) {
|
||||
|
||||
// If this is a copy operation, and the RHS is a known constant, assign its
|
||||
// value to the LHS.
|
||||
if (instr->opcode() == SpvOpCopyObject) {
|
||||
if (instr->opcode() == spv::Op::OpCopyObject) {
|
||||
uint32_t rhs_id = instr->GetSingleWordInOperand(0);
|
||||
auto it = values_.find(rhs_id);
|
||||
if (it != values_.end()) {
|
||||
@@ -211,10 +208,10 @@ SSAPropagator::PropStatus CCPPass::VisitBranch(Instruction* instr,
|
||||
|
||||
*dest_bb = nullptr;
|
||||
uint32_t dest_label = 0;
|
||||
if (instr->opcode() == SpvOpBranch) {
|
||||
if (instr->opcode() == spv::Op::OpBranch) {
|
||||
// An unconditional jump always goes to its unique destination.
|
||||
dest_label = instr->GetSingleWordInOperand(0);
|
||||
} else if (instr->opcode() == SpvOpBranchConditional) {
|
||||
} else if (instr->opcode() == spv::Op::OpBranchConditional) {
|
||||
// For a conditional branch, determine whether the predicate selector has a
|
||||
// known value in |values_|. If it does, set the destination block
|
||||
// according to the selector's boolean value.
|
||||
@@ -243,7 +240,7 @@ SSAPropagator::PropStatus CCPPass::VisitBranch(Instruction* instr,
|
||||
// For an OpSwitch, extract the value taken by the switch selector and check
|
||||
// which of the target literals it matches. The branch associated with that
|
||||
// literal is the taken branch.
|
||||
assert(instr->opcode() == SpvOpSwitch);
|
||||
assert(instr->opcode() == spv::Op::OpSwitch);
|
||||
if (instr->GetOperand(0).words.size() != 1) {
|
||||
// If the selector is wider than 32-bits, return varying. TODO(dnovillo):
|
||||
// Add support for wider constants.
|
||||
@@ -290,7 +287,7 @@ SSAPropagator::PropStatus CCPPass::VisitBranch(Instruction* instr,
|
||||
SSAPropagator::PropStatus CCPPass::VisitInstruction(Instruction* instr,
|
||||
BasicBlock** dest_bb) {
|
||||
*dest_bb = nullptr;
|
||||
if (instr->opcode() == SpvOpPhi) {
|
||||
if (instr->opcode() == spv::Op::OpPhi) {
|
||||
return VisitPhi(instr);
|
||||
} else if (instr->IsBranch()) {
|
||||
return VisitBranch(instr, dest_bb);
|
||||
|
||||
12
3rdparty/spirv-tools/source/opt/cfg.cpp
vendored
12
3rdparty/spirv-tools/source/opt/cfg.cpp
vendored
@@ -29,16 +29,16 @@ namespace {
|
||||
using cbb_ptr = const opt::BasicBlock*;
|
||||
|
||||
// Universal Limit of ResultID + 1
|
||||
const int kMaxResultId = 0x400000;
|
||||
constexpr int kMaxResultId = 0x400000;
|
||||
|
||||
} // namespace
|
||||
|
||||
CFG::CFG(Module* module)
|
||||
: module_(module),
|
||||
pseudo_entry_block_(std::unique_ptr<Instruction>(
|
||||
new Instruction(module->context(), SpvOpLabel, 0, 0, {}))),
|
||||
new Instruction(module->context(), spv::Op::OpLabel, 0, 0, {}))),
|
||||
pseudo_exit_block_(std::unique_ptr<Instruction>(new Instruction(
|
||||
module->context(), SpvOpLabel, 0, kMaxResultId, {}))) {
|
||||
module->context(), spv::Op::OpLabel, 0, kMaxResultId, {}))) {
|
||||
for (auto& fn : *module) {
|
||||
for (auto& blk : fn) {
|
||||
RegisterBlock(&blk);
|
||||
@@ -81,7 +81,7 @@ void CFG::ComputeStructuredOrder(Function* func, BasicBlock* root,
|
||||
BasicBlock* end,
|
||||
std::list<BasicBlock*>* order) {
|
||||
assert(module_->context()->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityShader) &&
|
||||
spv::Capability::Shader) &&
|
||||
"This only works on structured control flow");
|
||||
|
||||
// Compute structured successors and do DFS.
|
||||
@@ -228,7 +228,7 @@ BasicBlock* CFG::SplitLoopHeader(BasicBlock* bb) {
|
||||
// Create the new header bb basic bb.
|
||||
// Leave the phi instructions behind.
|
||||
auto iter = bb->begin();
|
||||
while (iter->opcode() == SpvOpPhi) {
|
||||
while (iter->opcode() == spv::Op::OpPhi) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ BasicBlock* CFG::SplitLoopHeader(BasicBlock* bb) {
|
||||
context, bb,
|
||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
||||
bb->AddInstruction(
|
||||
MakeUnique<Instruction>(context, SpvOpBranch, 0, 0,
|
||||
MakeUnique<Instruction>(context, spv::Op::OpBranch, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {new_header->id()}}}));
|
||||
context->AnalyzeUses(bb->terminator());
|
||||
|
||||
85
3rdparty/spirv-tools/source/opt/code_sink.cpp
vendored
85
3rdparty/spirv-tools/source/opt/code_sink.cpp
vendored
@@ -50,7 +50,8 @@ bool CodeSinkingPass::SinkInstructionsInBB(BasicBlock* bb) {
|
||||
}
|
||||
|
||||
bool CodeSinkingPass::SinkInstruction(Instruction* inst) {
|
||||
if (inst->opcode() != SpvOpLoad && inst->opcode() != SpvOpAccessChain) {
|
||||
if (inst->opcode() != spv::Op::OpLoad &&
|
||||
inst->opcode() != spv::Op::OpAccessChain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -60,7 +61,7 @@ bool CodeSinkingPass::SinkInstruction(Instruction* inst) {
|
||||
|
||||
if (BasicBlock* target_bb = FindNewBasicBlockFor(inst)) {
|
||||
Instruction* pos = &*target_bb->begin();
|
||||
while (pos->opcode() == SpvOpPhi) {
|
||||
while (pos->opcode() == spv::Op::OpPhi) {
|
||||
pos = pos->NextNode();
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ BasicBlock* CodeSinkingPass::FindNewBasicBlockFor(Instruction* inst) {
|
||||
std::unordered_set<uint32_t> bbs_with_uses;
|
||||
get_def_use_mgr()->ForEachUse(
|
||||
inst, [&bbs_with_uses, this](Instruction* use, uint32_t idx) {
|
||||
if (use->opcode() != SpvOpPhi) {
|
||||
if (use->opcode() != spv::Op::OpPhi) {
|
||||
BasicBlock* use_bb = context()->get_instr_block(use);
|
||||
if (use_bb) {
|
||||
bbs_with_uses.insert(use_bb->id());
|
||||
@@ -99,7 +100,7 @@ BasicBlock* CodeSinkingPass::FindNewBasicBlockFor(Instruction* inst) {
|
||||
// of succ_bb, then |inst| can be moved to succ_bb. If succ_bb, has move
|
||||
// then one predecessor, then moving |inst| into succ_bb could cause it to
|
||||
// be executed more often, so the search has to stop.
|
||||
if (bb->terminator()->opcode() == SpvOpBranch) {
|
||||
if (bb->terminator()->opcode() == spv::Op::OpBranch) {
|
||||
uint32_t succ_bb_id = bb->terminator()->GetSingleWordInOperand(0);
|
||||
if (cfg()->preds(succ_bb_id).size() == 1) {
|
||||
bb = context()->get_instr_block(succ_bb_id);
|
||||
@@ -113,7 +114,8 @@ BasicBlock* CodeSinkingPass::FindNewBasicBlockFor(Instruction* inst) {
|
||||
// instruction or an OpLoopMerge, then it is a break or continue. We could
|
||||
// figure it out, but not worth doing it now.
|
||||
Instruction* merge_inst = bb->GetMergeInst();
|
||||
if (merge_inst == nullptr || merge_inst->opcode() != SpvOpSelectionMerge) {
|
||||
if (merge_inst == nullptr ||
|
||||
merge_inst->opcode() != spv::Op::OpSelectionMerge) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -173,7 +175,7 @@ bool CodeSinkingPass::ReferencesMutableMemory(Instruction* inst) {
|
||||
}
|
||||
|
||||
Instruction* base_ptr = inst->GetBaseAddress();
|
||||
if (base_ptr->opcode() != SpvOpVariable) {
|
||||
if (base_ptr->opcode() != spv::Op::OpVariable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -185,7 +187,8 @@ bool CodeSinkingPass::ReferencesMutableMemory(Instruction* inst) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (base_ptr->GetSingleWordInOperand(0) != SpvStorageClassUniform) {
|
||||
if (spv::StorageClass(base_ptr->GetSingleWordInOperand(0)) !=
|
||||
spv::StorageClass::Uniform) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -200,41 +203,41 @@ bool CodeSinkingPass::HasUniformMemorySync() {
|
||||
bool has_sync = false;
|
||||
get_module()->ForEachInst([this, &has_sync](Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpMemoryBarrier: {
|
||||
case spv::Op::OpMemoryBarrier: {
|
||||
uint32_t mem_semantics_id = inst->GetSingleWordInOperand(1);
|
||||
if (IsSyncOnUniform(mem_semantics_id)) {
|
||||
has_sync = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SpvOpControlBarrier:
|
||||
case SpvOpAtomicLoad:
|
||||
case SpvOpAtomicStore:
|
||||
case SpvOpAtomicExchange:
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicFAddEXT:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
case SpvOpAtomicFMinEXT:
|
||||
case SpvOpAtomicSMax:
|
||||
case SpvOpAtomicUMax:
|
||||
case SpvOpAtomicFMaxEXT:
|
||||
case SpvOpAtomicAnd:
|
||||
case SpvOpAtomicOr:
|
||||
case SpvOpAtomicXor:
|
||||
case SpvOpAtomicFlagTestAndSet:
|
||||
case SpvOpAtomicFlagClear: {
|
||||
case spv::Op::OpControlBarrier:
|
||||
case spv::Op::OpAtomicLoad:
|
||||
case spv::Op::OpAtomicStore:
|
||||
case spv::Op::OpAtomicExchange:
|
||||
case spv::Op::OpAtomicIIncrement:
|
||||
case spv::Op::OpAtomicIDecrement:
|
||||
case spv::Op::OpAtomicIAdd:
|
||||
case spv::Op::OpAtomicFAddEXT:
|
||||
case spv::Op::OpAtomicISub:
|
||||
case spv::Op::OpAtomicSMin:
|
||||
case spv::Op::OpAtomicUMin:
|
||||
case spv::Op::OpAtomicFMinEXT:
|
||||
case spv::Op::OpAtomicSMax:
|
||||
case spv::Op::OpAtomicUMax:
|
||||
case spv::Op::OpAtomicFMaxEXT:
|
||||
case spv::Op::OpAtomicAnd:
|
||||
case spv::Op::OpAtomicOr:
|
||||
case spv::Op::OpAtomicXor:
|
||||
case spv::Op::OpAtomicFlagTestAndSet:
|
||||
case spv::Op::OpAtomicFlagClear: {
|
||||
uint32_t mem_semantics_id = inst->GetSingleWordInOperand(2);
|
||||
if (IsSyncOnUniform(mem_semantics_id)) {
|
||||
has_sync = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SpvOpAtomicCompareExchange:
|
||||
case SpvOpAtomicCompareExchangeWeak:
|
||||
case spv::Op::OpAtomicCompareExchange:
|
||||
case spv::Op::OpAtomicCompareExchangeWeak:
|
||||
if (IsSyncOnUniform(inst->GetSingleWordInOperand(2)) ||
|
||||
IsSyncOnUniform(inst->GetSingleWordInOperand(3))) {
|
||||
has_sync = true;
|
||||
@@ -259,28 +262,30 @@ bool CodeSinkingPass::IsSyncOnUniform(uint32_t mem_semantics_id) const {
|
||||
|
||||
// If it does not affect uniform memory, then it is does not apply to uniform
|
||||
// memory.
|
||||
if ((mem_semantics_int & SpvMemorySemanticsUniformMemoryMask) == 0) {
|
||||
if ((mem_semantics_int & uint32_t(spv::MemorySemanticsMask::UniformMemory)) ==
|
||||
0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if there is an acquire or release. If so not, this it does not add
|
||||
// any memory constraints.
|
||||
return (mem_semantics_int & (SpvMemorySemanticsAcquireMask |
|
||||
SpvMemorySemanticsAcquireReleaseMask |
|
||||
SpvMemorySemanticsReleaseMask)) != 0;
|
||||
return (mem_semantics_int &
|
||||
uint32_t(spv::MemorySemanticsMask::Acquire |
|
||||
spv::MemorySemanticsMask::AcquireRelease |
|
||||
spv::MemorySemanticsMask::Release)) != 0;
|
||||
}
|
||||
|
||||
bool CodeSinkingPass::HasPossibleStore(Instruction* var_inst) {
|
||||
assert(var_inst->opcode() == SpvOpVariable ||
|
||||
var_inst->opcode() == SpvOpAccessChain ||
|
||||
var_inst->opcode() == SpvOpPtrAccessChain);
|
||||
assert(var_inst->opcode() == spv::Op::OpVariable ||
|
||||
var_inst->opcode() == spv::Op::OpAccessChain ||
|
||||
var_inst->opcode() == spv::Op::OpPtrAccessChain);
|
||||
|
||||
return get_def_use_mgr()->WhileEachUser(var_inst, [this](Instruction* use) {
|
||||
switch (use->opcode()) {
|
||||
case SpvOpStore:
|
||||
case spv::Op::OpStore:
|
||||
return true;
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
return HasPossibleStore(use);
|
||||
default:
|
||||
return false;
|
||||
|
||||
@@ -44,10 +44,10 @@ bool CombineAccessChains::ProcessFunction(Function& function) {
|
||||
function.entry().get(), [&modified, this](BasicBlock* block) {
|
||||
block->ForEachInst([&modified, this](Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
modified |= CombineAccessChain(inst);
|
||||
break;
|
||||
default:
|
||||
@@ -76,10 +76,10 @@ uint32_t CombineAccessChains::GetConstantValue(
|
||||
uint32_t CombineAccessChains::GetArrayStride(const Instruction* inst) {
|
||||
uint32_t array_stride = 0;
|
||||
context()->get_decoration_mgr()->WhileEachDecoration(
|
||||
inst->type_id(), SpvDecorationArrayStride,
|
||||
inst->type_id(), uint32_t(spv::Decoration::ArrayStride),
|
||||
[&array_stride](const Instruction& decoration) {
|
||||
assert(decoration.opcode() != SpvOpDecorateId);
|
||||
if (decoration.opcode() == SpvOpDecorate) {
|
||||
assert(decoration.opcode() != spv::Op::OpDecorateId);
|
||||
if (decoration.opcode() == spv::Op::OpDecorate) {
|
||||
array_stride = decoration.GetSingleWordInOperand(1);
|
||||
} else {
|
||||
array_stride = decoration.GetSingleWordInOperand(2);
|
||||
@@ -200,18 +200,18 @@ bool CombineAccessChains::CreateNewInputOperands(
|
||||
}
|
||||
|
||||
bool CombineAccessChains::CombineAccessChain(Instruction* inst) {
|
||||
assert((inst->opcode() == SpvOpPtrAccessChain ||
|
||||
inst->opcode() == SpvOpAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsPtrAccessChain) &&
|
||||
assert((inst->opcode() == spv::Op::OpPtrAccessChain ||
|
||||
inst->opcode() == spv::Op::OpAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) &&
|
||||
"Wrong opcode. Expected an access chain.");
|
||||
|
||||
Instruction* ptr_input =
|
||||
context()->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0));
|
||||
if (ptr_input->opcode() != SpvOpAccessChain &&
|
||||
ptr_input->opcode() != SpvOpInBoundsAccessChain &&
|
||||
ptr_input->opcode() != SpvOpPtrAccessChain &&
|
||||
ptr_input->opcode() != SpvOpInBoundsPtrAccessChain) {
|
||||
if (ptr_input->opcode() != spv::Op::OpAccessChain &&
|
||||
ptr_input->opcode() != spv::Op::OpInBoundsAccessChain &&
|
||||
ptr_input->opcode() != spv::Op::OpPtrAccessChain &&
|
||||
ptr_input->opcode() != spv::Op::OpInBoundsPtrAccessChain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ bool CombineAccessChains::CombineAccessChain(Instruction* inst) {
|
||||
} else if (inst->NumInOperands() == 1) {
|
||||
// |inst| is a no-op, change it to a copy. Instruction simplification will
|
||||
// clean it up.
|
||||
inst->SetOpcode(SpvOpCopyObject);
|
||||
inst->SetOpcode(spv::Op::OpCopyObject);
|
||||
} else {
|
||||
std::vector<Operand> new_operands;
|
||||
if (!CreateNewInputOperands(ptr_input, inst, &new_operands)) return false;
|
||||
@@ -259,23 +259,25 @@ bool CombineAccessChains::CombineAccessChain(Instruction* inst) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SpvOp CombineAccessChains::UpdateOpcode(SpvOp base_opcode, SpvOp input_opcode) {
|
||||
auto IsInBounds = [](SpvOp opcode) {
|
||||
return opcode == SpvOpInBoundsPtrAccessChain ||
|
||||
opcode == SpvOpInBoundsAccessChain;
|
||||
spv::Op CombineAccessChains::UpdateOpcode(spv::Op base_opcode,
|
||||
spv::Op input_opcode) {
|
||||
auto IsInBounds = [](spv::Op opcode) {
|
||||
return opcode == spv::Op::OpInBoundsPtrAccessChain ||
|
||||
opcode == spv::Op::OpInBoundsAccessChain;
|
||||
};
|
||||
|
||||
if (input_opcode == SpvOpInBoundsPtrAccessChain) {
|
||||
if (!IsInBounds(base_opcode)) return SpvOpPtrAccessChain;
|
||||
} else if (input_opcode == SpvOpInBoundsAccessChain) {
|
||||
if (!IsInBounds(base_opcode)) return SpvOpAccessChain;
|
||||
if (input_opcode == spv::Op::OpInBoundsPtrAccessChain) {
|
||||
if (!IsInBounds(base_opcode)) return spv::Op::OpPtrAccessChain;
|
||||
} else if (input_opcode == spv::Op::OpInBoundsAccessChain) {
|
||||
if (!IsInBounds(base_opcode)) return spv::Op::OpAccessChain;
|
||||
}
|
||||
|
||||
return input_opcode;
|
||||
}
|
||||
|
||||
bool CombineAccessChains::IsPtrAccessChain(SpvOp opcode) {
|
||||
return opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain;
|
||||
bool CombineAccessChains::IsPtrAccessChain(spv::Op opcode) {
|
||||
return opcode == spv::Op::OpPtrAccessChain ||
|
||||
opcode == spv::Op::OpInBoundsPtrAccessChain;
|
||||
}
|
||||
|
||||
bool CombineAccessChains::Has64BitIndices(Instruction* inst) {
|
||||
|
||||
@@ -68,10 +68,10 @@ class CombineAccessChains : public Pass {
|
||||
std::vector<Operand>* new_operands);
|
||||
|
||||
// Returns the opcode to use for the combined access chain.
|
||||
SpvOp UpdateOpcode(SpvOp base_opcode, SpvOp input_opcode);
|
||||
spv::Op UpdateOpcode(spv::Op base_opcode, spv::Op input_opcode);
|
||||
|
||||
// Returns true if |opcode| is a pointer access chain.
|
||||
bool IsPtrAccessChain(SpvOp opcode);
|
||||
bool IsPtrAccessChain(spv::Op opcode);
|
||||
|
||||
// Returns true if |inst| (an access chain) has 64-bit indices.
|
||||
bool Has64BitIndices(Instruction* inst);
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
|
||||
const uint32_t kExtractCompositeIdInIdx = 0;
|
||||
constexpr uint32_t kExtractCompositeIdInIdx = 0;
|
||||
|
||||
// Returns a constants with the value NaN of the given type. Only works for
|
||||
// 32-bit and 64-bit float point types. Returns |nullptr| if an error occurs.
|
||||
@@ -120,11 +119,97 @@ ConstantFoldingRule FoldExtractWithConstants() {
|
||||
};
|
||||
}
|
||||
|
||||
// Folds an OpcompositeInsert where input is a composite constant.
|
||||
ConstantFoldingRule FoldInsertWithConstants() {
|
||||
return [](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants)
|
||||
-> const analysis::Constant* {
|
||||
analysis::ConstantManager* const_mgr = context->get_constant_mgr();
|
||||
const analysis::Constant* object = constants[0];
|
||||
const analysis::Constant* composite = constants[1];
|
||||
if (object == nullptr || composite == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If there is more than 1 index, then each additional constant used by the
|
||||
// index will need to be recreated to use the inserted object.
|
||||
std::vector<const analysis::Constant*> chain;
|
||||
std::vector<const analysis::Constant*> components;
|
||||
const analysis::Type* type = nullptr;
|
||||
const uint32_t final_index = (inst->NumInOperands() - 1);
|
||||
|
||||
// Work down hierarchy of all indexes
|
||||
for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
|
||||
type = composite->type();
|
||||
|
||||
if (composite->AsNullConstant()) {
|
||||
// Make new composite so it can be inserted in the index with the
|
||||
// non-null value
|
||||
const auto new_composite = const_mgr->GetNullCompositeConstant(type);
|
||||
// Keep track of any indexes along the way to last index
|
||||
if (i != final_index) {
|
||||
chain.push_back(new_composite);
|
||||
}
|
||||
components = new_composite->AsCompositeConstant()->GetComponents();
|
||||
} else {
|
||||
// Keep track of any indexes along the way to last index
|
||||
if (i != final_index) {
|
||||
chain.push_back(composite);
|
||||
}
|
||||
components = composite->AsCompositeConstant()->GetComponents();
|
||||
}
|
||||
const uint32_t index = inst->GetSingleWordInOperand(i);
|
||||
composite = components[index];
|
||||
}
|
||||
|
||||
// Final index in hierarchy is inserted with new object.
|
||||
const uint32_t final_operand = inst->GetSingleWordInOperand(final_index);
|
||||
std::vector<uint32_t> ids;
|
||||
for (size_t i = 0; i < components.size(); i++) {
|
||||
const analysis::Constant* constant =
|
||||
(i == final_operand) ? object : components[i];
|
||||
Instruction* member_inst = const_mgr->GetDefiningInstruction(constant);
|
||||
ids.push_back(member_inst->result_id());
|
||||
}
|
||||
const analysis::Constant* new_constant = const_mgr->GetConstant(type, ids);
|
||||
|
||||
// Work backwards up the chain and replace each index with new constant.
|
||||
for (size_t i = chain.size(); i > 0; i--) {
|
||||
// Need to insert any previous instruction into the module first.
|
||||
// Can't just insert in types_values_begin() because it will move above
|
||||
// where the types are declared.
|
||||
// Can't compare with location of inst because not all new added
|
||||
// instructions are added to types_values_
|
||||
auto iter = context->types_values_end();
|
||||
Module::inst_iterator* pos = &iter;
|
||||
const_mgr->BuildInstructionAndAddToModule(new_constant, pos);
|
||||
|
||||
composite = chain[i - 1];
|
||||
components = composite->AsCompositeConstant()->GetComponents();
|
||||
type = composite->type();
|
||||
ids.clear();
|
||||
for (size_t k = 0; k < components.size(); k++) {
|
||||
const uint32_t index =
|
||||
inst->GetSingleWordInOperand(1 + static_cast<uint32_t>(i));
|
||||
const analysis::Constant* constant =
|
||||
(k == index) ? new_constant : components[k];
|
||||
const uint32_t constant_id =
|
||||
const_mgr->FindDeclaredConstant(constant, 0);
|
||||
ids.push_back(constant_id);
|
||||
}
|
||||
new_constant = const_mgr->GetConstant(type, ids);
|
||||
}
|
||||
|
||||
// If multiple constants were created, only need to return the top index.
|
||||
return new_constant;
|
||||
};
|
||||
}
|
||||
|
||||
ConstantFoldingRule FoldVectorShuffleWithConstants() {
|
||||
return [](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants)
|
||||
-> const analysis::Constant* {
|
||||
assert(inst->opcode() == SpvOpVectorShuffle);
|
||||
assert(inst->opcode() == spv::Op::OpVectorShuffle);
|
||||
const analysis::Constant* c1 = constants[0];
|
||||
const analysis::Constant* c2 = constants[1];
|
||||
if (c1 == nullptr || c2 == nullptr) {
|
||||
@@ -180,7 +265,7 @@ ConstantFoldingRule FoldVectorTimesScalar() {
|
||||
return [](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants)
|
||||
-> const analysis::Constant* {
|
||||
assert(inst->opcode() == SpvOpVectorTimesScalar);
|
||||
assert(inst->opcode() == spv::Op::OpVectorTimesScalar);
|
||||
analysis::ConstantManager* const_mgr = context->get_constant_mgr();
|
||||
analysis::TypeManager* type_mgr = context->get_type_mgr();
|
||||
|
||||
@@ -255,7 +340,7 @@ ConstantFoldingRule FoldVectorTimesMatrix() {
|
||||
return [](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants)
|
||||
-> const analysis::Constant* {
|
||||
assert(inst->opcode() == SpvOpVectorTimesMatrix);
|
||||
assert(inst->opcode() == spv::Op::OpVectorTimesMatrix);
|
||||
analysis::ConstantManager* const_mgr = context->get_constant_mgr();
|
||||
analysis::TypeManager* type_mgr = context->get_type_mgr();
|
||||
|
||||
@@ -348,7 +433,7 @@ ConstantFoldingRule FoldMatrixTimesVector() {
|
||||
return [](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants)
|
||||
-> const analysis::Constant* {
|
||||
assert(inst->opcode() == SpvOpMatrixTimesVector);
|
||||
assert(inst->opcode() == spv::Op::OpMatrixTimesVector);
|
||||
analysis::ConstantManager* const_mgr = context->get_constant_mgr();
|
||||
analysis::TypeManager* type_mgr = context->get_type_mgr();
|
||||
|
||||
@@ -458,9 +543,9 @@ ConstantFoldingRule FoldCompositeWithConstants() {
|
||||
}
|
||||
|
||||
uint32_t component_type_id = 0;
|
||||
if (type_inst->opcode() == SpvOpTypeStruct) {
|
||||
if (type_inst->opcode() == spv::Op::OpTypeStruct) {
|
||||
component_type_id = type_inst->GetSingleWordInOperand(i);
|
||||
} else if (type_inst->opcode() == SpvOpTypeArray) {
|
||||
} else if (type_inst->opcode() == spv::Op::OpTypeArray) {
|
||||
component_type_id = type_inst->GetSingleWordInOperand(0);
|
||||
}
|
||||
|
||||
@@ -509,7 +594,7 @@ ConstantFoldingRule FoldFPUnaryOp(UnaryScalarFoldingRule scalar_rule) {
|
||||
}
|
||||
|
||||
const analysis::Constant* arg =
|
||||
(inst->opcode() == SpvOpExtInst) ? constants[1] : constants[0];
|
||||
(inst->opcode() == spv::Op::OpExtInst) ? constants[1] : constants[0];
|
||||
|
||||
if (arg == nullptr) {
|
||||
return nullptr;
|
||||
@@ -599,7 +684,7 @@ ConstantFoldingRule FoldFPBinaryOp(BinaryScalarFoldingRule scalar_rule) {
|
||||
if (!inst->IsFloatingPointFoldingAllowed()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (inst->opcode() == SpvOpExtInst) {
|
||||
if (inst->opcode() == spv::Op::OpExtInst) {
|
||||
return FoldFPBinaryOp(scalar_rule, inst->type_id(),
|
||||
{constants[1], constants[2]}, context);
|
||||
}
|
||||
@@ -957,7 +1042,7 @@ UnaryScalarFoldingRule FoldFNegateOp() {
|
||||
|
||||
ConstantFoldingRule FoldFNegate() { return FoldFPUnaryOp(FoldFNegateOp()); }
|
||||
|
||||
ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
|
||||
ConstantFoldingRule FoldFClampFeedingCompare(spv::Op cmp_opcode) {
|
||||
return [cmp_opcode](IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants)
|
||||
-> const analysis::Constant* {
|
||||
@@ -985,7 +1070,7 @@ ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (operand_inst->opcode() != SpvOpExtInst) {
|
||||
if (operand_inst->opcode() != spv::Op::OpExtInst) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1009,25 +1094,25 @@ ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
|
||||
bool result = false;
|
||||
|
||||
switch (cmp_opcode) {
|
||||
case SpvOpFOrdLessThan:
|
||||
case SpvOpFUnordLessThan:
|
||||
case SpvOpFOrdGreaterThanEqual:
|
||||
case SpvOpFUnordGreaterThanEqual:
|
||||
case spv::Op::OpFOrdLessThan:
|
||||
case spv::Op::OpFUnordLessThan:
|
||||
case spv::Op::OpFOrdGreaterThanEqual:
|
||||
case spv::Op::OpFUnordGreaterThanEqual:
|
||||
if (constants[0]) {
|
||||
if (min_const) {
|
||||
if (constants[0]->GetValueAsDouble() <
|
||||
min_const->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = (cmp_opcode == SpvOpFOrdLessThan ||
|
||||
cmp_opcode == SpvOpFUnordLessThan);
|
||||
result = (cmp_opcode == spv::Op::OpFOrdLessThan ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThan);
|
||||
}
|
||||
}
|
||||
if (max_const) {
|
||||
if (constants[0]->GetValueAsDouble() >=
|
||||
max_const->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = !(cmp_opcode == SpvOpFOrdLessThan ||
|
||||
cmp_opcode == SpvOpFUnordLessThan);
|
||||
result = !(cmp_opcode == spv::Op::OpFOrdLessThan ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThan);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1037,8 +1122,8 @@ ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
|
||||
if (max_const->GetValueAsDouble() <
|
||||
constants[1]->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = (cmp_opcode == SpvOpFOrdLessThan ||
|
||||
cmp_opcode == SpvOpFUnordLessThan);
|
||||
result = (cmp_opcode == spv::Op::OpFOrdLessThan ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThan);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1046,31 +1131,31 @@ ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
|
||||
if (min_const->GetValueAsDouble() >=
|
||||
constants[1]->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = !(cmp_opcode == SpvOpFOrdLessThan ||
|
||||
cmp_opcode == SpvOpFUnordLessThan);
|
||||
result = !(cmp_opcode == spv::Op::OpFOrdLessThan ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThan);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvOpFOrdGreaterThan:
|
||||
case SpvOpFUnordGreaterThan:
|
||||
case SpvOpFOrdLessThanEqual:
|
||||
case SpvOpFUnordLessThanEqual:
|
||||
case spv::Op::OpFOrdGreaterThan:
|
||||
case spv::Op::OpFUnordGreaterThan:
|
||||
case spv::Op::OpFOrdLessThanEqual:
|
||||
case spv::Op::OpFUnordLessThanEqual:
|
||||
if (constants[0]) {
|
||||
if (min_const) {
|
||||
if (constants[0]->GetValueAsDouble() <=
|
||||
min_const->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = (cmp_opcode == SpvOpFOrdLessThanEqual ||
|
||||
cmp_opcode == SpvOpFUnordLessThanEqual);
|
||||
result = (cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThanEqual);
|
||||
}
|
||||
}
|
||||
if (max_const) {
|
||||
if (constants[0]->GetValueAsDouble() >
|
||||
max_const->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = !(cmp_opcode == SpvOpFOrdLessThanEqual ||
|
||||
cmp_opcode == SpvOpFUnordLessThanEqual);
|
||||
result = !(cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThanEqual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1080,8 +1165,8 @@ ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
|
||||
if (max_const->GetValueAsDouble() <=
|
||||
constants[1]->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = (cmp_opcode == SpvOpFOrdLessThanEqual ||
|
||||
cmp_opcode == SpvOpFUnordLessThanEqual);
|
||||
result = (cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThanEqual);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,8 +1174,8 @@ ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
|
||||
if (min_const->GetValueAsDouble() >
|
||||
constants[1]->GetValueAsDouble()) {
|
||||
found_result = true;
|
||||
result = !(cmp_opcode == SpvOpFOrdLessThanEqual ||
|
||||
cmp_opcode == SpvOpFUnordLessThanEqual);
|
||||
result = !(cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
|
||||
cmp_opcode == spv::Op::OpFUnordLessThanEqual);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1117,7 +1202,7 @@ ConstantFoldingRule FoldFMix() {
|
||||
const std::vector<const analysis::Constant*>& constants)
|
||||
-> const analysis::Constant* {
|
||||
analysis::ConstantManager* const_mgr = context->get_constant_mgr();
|
||||
assert(inst->opcode() == SpvOpExtInst &&
|
||||
assert(inst->opcode() == spv::Op::OpExtInst &&
|
||||
"Expecting an extended instruction.");
|
||||
assert(inst->GetSingleWordInOperand(0) ==
|
||||
context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
|
||||
@@ -1267,7 +1352,7 @@ const analysis::Constant* FoldMax(const analysis::Type* result_type,
|
||||
const analysis::Constant* FoldClamp1(
|
||||
IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants) {
|
||||
assert(inst->opcode() == SpvOpExtInst &&
|
||||
assert(inst->opcode() == spv::Op::OpExtInst &&
|
||||
"Expecting an extended instruction.");
|
||||
assert(inst->GetSingleWordInOperand(0) ==
|
||||
context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
|
||||
@@ -1293,7 +1378,7 @@ const analysis::Constant* FoldClamp1(
|
||||
const analysis::Constant* FoldClamp2(
|
||||
IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants) {
|
||||
assert(inst->opcode() == SpvOpExtInst &&
|
||||
assert(inst->opcode() == spv::Op::OpExtInst &&
|
||||
"Expecting an extended instruction.");
|
||||
assert(inst->GetSingleWordInOperand(0) ==
|
||||
context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
|
||||
@@ -1321,7 +1406,7 @@ const analysis::Constant* FoldClamp2(
|
||||
const analysis::Constant* FoldClamp3(
|
||||
IRContext* context, Instruction* inst,
|
||||
const std::vector<const analysis::Constant*>& constants) {
|
||||
assert(inst->opcode() == SpvOpExtInst &&
|
||||
assert(inst->opcode() == spv::Op::OpExtInst &&
|
||||
"Expecting an extended instruction.");
|
||||
assert(inst->GetSingleWordInOperand(0) ==
|
||||
context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
|
||||
@@ -1407,68 +1492,70 @@ void ConstantFoldingRules::AddFoldingRules() {
|
||||
// applies to the instruction, the rest of the rules will not be attempted.
|
||||
// Take that into consideration.
|
||||
|
||||
rules_[SpvOpCompositeConstruct].push_back(FoldCompositeWithConstants());
|
||||
rules_[spv::Op::OpCompositeConstruct].push_back(FoldCompositeWithConstants());
|
||||
|
||||
rules_[SpvOpCompositeExtract].push_back(FoldExtractWithConstants());
|
||||
rules_[spv::Op::OpCompositeExtract].push_back(FoldExtractWithConstants());
|
||||
rules_[spv::Op::OpCompositeInsert].push_back(FoldInsertWithConstants());
|
||||
|
||||
rules_[SpvOpConvertFToS].push_back(FoldFToI());
|
||||
rules_[SpvOpConvertFToU].push_back(FoldFToI());
|
||||
rules_[SpvOpConvertSToF].push_back(FoldIToF());
|
||||
rules_[SpvOpConvertUToF].push_back(FoldIToF());
|
||||
rules_[spv::Op::OpConvertFToS].push_back(FoldFToI());
|
||||
rules_[spv::Op::OpConvertFToU].push_back(FoldFToI());
|
||||
rules_[spv::Op::OpConvertSToF].push_back(FoldIToF());
|
||||
rules_[spv::Op::OpConvertUToF].push_back(FoldIToF());
|
||||
|
||||
rules_[SpvOpDot].push_back(FoldOpDotWithConstants());
|
||||
rules_[SpvOpFAdd].push_back(FoldFAdd());
|
||||
rules_[SpvOpFDiv].push_back(FoldFDiv());
|
||||
rules_[SpvOpFMul].push_back(FoldFMul());
|
||||
rules_[SpvOpFSub].push_back(FoldFSub());
|
||||
rules_[spv::Op::OpDot].push_back(FoldOpDotWithConstants());
|
||||
rules_[spv::Op::OpFAdd].push_back(FoldFAdd());
|
||||
rules_[spv::Op::OpFDiv].push_back(FoldFDiv());
|
||||
rules_[spv::Op::OpFMul].push_back(FoldFMul());
|
||||
rules_[spv::Op::OpFSub].push_back(FoldFSub());
|
||||
|
||||
rules_[SpvOpFOrdEqual].push_back(FoldFOrdEqual());
|
||||
rules_[spv::Op::OpFOrdEqual].push_back(FoldFOrdEqual());
|
||||
|
||||
rules_[SpvOpFUnordEqual].push_back(FoldFUnordEqual());
|
||||
rules_[spv::Op::OpFUnordEqual].push_back(FoldFUnordEqual());
|
||||
|
||||
rules_[SpvOpFOrdNotEqual].push_back(FoldFOrdNotEqual());
|
||||
rules_[spv::Op::OpFOrdNotEqual].push_back(FoldFOrdNotEqual());
|
||||
|
||||
rules_[SpvOpFUnordNotEqual].push_back(FoldFUnordNotEqual());
|
||||
rules_[spv::Op::OpFUnordNotEqual].push_back(FoldFUnordNotEqual());
|
||||
|
||||
rules_[SpvOpFOrdLessThan].push_back(FoldFOrdLessThan());
|
||||
rules_[SpvOpFOrdLessThan].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFOrdLessThan));
|
||||
rules_[spv::Op::OpFOrdLessThan].push_back(FoldFOrdLessThan());
|
||||
rules_[spv::Op::OpFOrdLessThan].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFOrdLessThan));
|
||||
|
||||
rules_[SpvOpFUnordLessThan].push_back(FoldFUnordLessThan());
|
||||
rules_[SpvOpFUnordLessThan].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFUnordLessThan));
|
||||
rules_[spv::Op::OpFUnordLessThan].push_back(FoldFUnordLessThan());
|
||||
rules_[spv::Op::OpFUnordLessThan].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFUnordLessThan));
|
||||
|
||||
rules_[SpvOpFOrdGreaterThan].push_back(FoldFOrdGreaterThan());
|
||||
rules_[SpvOpFOrdGreaterThan].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFOrdGreaterThan));
|
||||
rules_[spv::Op::OpFOrdGreaterThan].push_back(FoldFOrdGreaterThan());
|
||||
rules_[spv::Op::OpFOrdGreaterThan].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFOrdGreaterThan));
|
||||
|
||||
rules_[SpvOpFUnordGreaterThan].push_back(FoldFUnordGreaterThan());
|
||||
rules_[SpvOpFUnordGreaterThan].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFUnordGreaterThan));
|
||||
rules_[spv::Op::OpFUnordGreaterThan].push_back(FoldFUnordGreaterThan());
|
||||
rules_[spv::Op::OpFUnordGreaterThan].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFUnordGreaterThan));
|
||||
|
||||
rules_[SpvOpFOrdLessThanEqual].push_back(FoldFOrdLessThanEqual());
|
||||
rules_[SpvOpFOrdLessThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFOrdLessThanEqual));
|
||||
rules_[spv::Op::OpFOrdLessThanEqual].push_back(FoldFOrdLessThanEqual());
|
||||
rules_[spv::Op::OpFOrdLessThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFOrdLessThanEqual));
|
||||
|
||||
rules_[SpvOpFUnordLessThanEqual].push_back(FoldFUnordLessThanEqual());
|
||||
rules_[SpvOpFUnordLessThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFUnordLessThanEqual));
|
||||
rules_[spv::Op::OpFUnordLessThanEqual].push_back(FoldFUnordLessThanEqual());
|
||||
rules_[spv::Op::OpFUnordLessThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFUnordLessThanEqual));
|
||||
|
||||
rules_[SpvOpFOrdGreaterThanEqual].push_back(FoldFOrdGreaterThanEqual());
|
||||
rules_[SpvOpFOrdGreaterThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFOrdGreaterThanEqual));
|
||||
rules_[spv::Op::OpFOrdGreaterThanEqual].push_back(FoldFOrdGreaterThanEqual());
|
||||
rules_[spv::Op::OpFOrdGreaterThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFOrdGreaterThanEqual));
|
||||
|
||||
rules_[SpvOpFUnordGreaterThanEqual].push_back(FoldFUnordGreaterThanEqual());
|
||||
rules_[SpvOpFUnordGreaterThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(SpvOpFUnordGreaterThanEqual));
|
||||
rules_[spv::Op::OpFUnordGreaterThanEqual].push_back(
|
||||
FoldFUnordGreaterThanEqual());
|
||||
rules_[spv::Op::OpFUnordGreaterThanEqual].push_back(
|
||||
FoldFClampFeedingCompare(spv::Op::OpFUnordGreaterThanEqual));
|
||||
|
||||
rules_[SpvOpVectorShuffle].push_back(FoldVectorShuffleWithConstants());
|
||||
rules_[SpvOpVectorTimesScalar].push_back(FoldVectorTimesScalar());
|
||||
rules_[SpvOpVectorTimesMatrix].push_back(FoldVectorTimesMatrix());
|
||||
rules_[SpvOpMatrixTimesVector].push_back(FoldMatrixTimesVector());
|
||||
rules_[spv::Op::OpVectorShuffle].push_back(FoldVectorShuffleWithConstants());
|
||||
rules_[spv::Op::OpVectorTimesScalar].push_back(FoldVectorTimesScalar());
|
||||
rules_[spv::Op::OpVectorTimesMatrix].push_back(FoldVectorTimesMatrix());
|
||||
rules_[spv::Op::OpMatrixTimesVector].push_back(FoldMatrixTimesVector());
|
||||
|
||||
rules_[SpvOpFNegate].push_back(FoldFNegate());
|
||||
rules_[SpvOpQuantizeToF16].push_back(FoldQuantizeToF16());
|
||||
rules_[spv::Op::OpFNegate].push_back(FoldFNegate());
|
||||
rules_[spv::Op::OpQuantizeToF16].push_back(FoldQuantizeToF16());
|
||||
|
||||
// Add rules for GLSLstd450
|
||||
FeatureManager* feature_manager = context_->get_feature_mgr();
|
||||
|
||||
@@ -88,7 +88,7 @@ class ConstantFoldingRules {
|
||||
// Returns true if there is at least 1 folding rule for |inst|.
|
||||
const std::vector<ConstantFoldingRule>& GetRulesForInstruction(
|
||||
const Instruction* inst) const {
|
||||
if (inst->opcode() != SpvOpExtInst) {
|
||||
if (inst->opcode() != spv::Op::OpExtInst) {
|
||||
auto it = rules_.find(inst->opcode());
|
||||
if (it != rules_.end()) {
|
||||
return it->second.value;
|
||||
@@ -108,9 +108,15 @@ class ConstantFoldingRules {
|
||||
virtual void AddFoldingRules();
|
||||
|
||||
protected:
|
||||
struct hasher {
|
||||
size_t operator()(const spv::Op& op) const noexcept {
|
||||
return std::hash<uint32_t>()(uint32_t(op));
|
||||
}
|
||||
};
|
||||
|
||||
// |rules[opcode]| is the set of rules that can be applied to instructions
|
||||
// with |opcode| as the opcode.
|
||||
std::unordered_map<uint32_t, Value> rules_;
|
||||
std::unordered_map<spv::Op, Value, hasher> rules_;
|
||||
|
||||
// The folding rules for extended instructions.
|
||||
std::map<Key, Value> ext_rules_;
|
||||
|
||||
76
3rdparty/spirv-tools/source/opt/constants.cpp
vendored
76
3rdparty/spirv-tools/source/opt/constants.cpp
vendored
@@ -306,16 +306,16 @@ const Constant* ConstantManager::GetConstantFromInst(const Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
// OpConstant{True|False} have the value embedded in the opcode. So they
|
||||
// are not handled by the for-loop above. Here we add the value explicitly.
|
||||
case SpvOp::SpvOpConstantTrue:
|
||||
case spv::Op::OpConstantTrue:
|
||||
literal_words_or_ids.push_back(true);
|
||||
break;
|
||||
case SpvOp::SpvOpConstantFalse:
|
||||
case spv::Op::OpConstantFalse:
|
||||
literal_words_or_ids.push_back(false);
|
||||
break;
|
||||
case SpvOp::SpvOpConstantNull:
|
||||
case SpvOp::SpvOpConstant:
|
||||
case SpvOp::SpvOpConstantComposite:
|
||||
case SpvOp::SpvOpSpecConstantComposite:
|
||||
case spv::Op::OpConstantNull:
|
||||
case spv::Op::OpConstant:
|
||||
case spv::Op::OpConstantComposite:
|
||||
case spv::Op::OpSpecConstantComposite:
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
@@ -329,22 +329,22 @@ std::unique_ptr<Instruction> ConstantManager::CreateInstruction(
|
||||
uint32_t type =
|
||||
(type_id == 0) ? context()->get_type_mgr()->GetId(c->type()) : type_id;
|
||||
if (c->AsNullConstant()) {
|
||||
return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantNull, type,
|
||||
id, std::initializer_list<Operand>{});
|
||||
return MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, type, id,
|
||||
std::initializer_list<Operand>{});
|
||||
} else if (const BoolConstant* bc = c->AsBoolConstant()) {
|
||||
return MakeUnique<Instruction>(
|
||||
context(),
|
||||
bc->value() ? SpvOp::SpvOpConstantTrue : SpvOp::SpvOpConstantFalse,
|
||||
type, id, std::initializer_list<Operand>{});
|
||||
bc->value() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse, type,
|
||||
id, std::initializer_list<Operand>{});
|
||||
} else if (const IntConstant* ic = c->AsIntConstant()) {
|
||||
return MakeUnique<Instruction>(
|
||||
context(), SpvOp::SpvOpConstant, type, id,
|
||||
context(), spv::Op::OpConstant, type, id,
|
||||
std::initializer_list<Operand>{
|
||||
Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
|
||||
ic->words())});
|
||||
} else if (const FloatConstant* fc = c->AsFloatConstant()) {
|
||||
return MakeUnique<Instruction>(
|
||||
context(), SpvOp::SpvOpConstant, type, id,
|
||||
context(), spv::Op::OpConstant, type, id,
|
||||
std::initializer_list<Operand>{
|
||||
Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
|
||||
fc->words())});
|
||||
@@ -362,9 +362,9 @@ std::unique_ptr<Instruction> ConstantManager::CreateCompositeInstruction(
|
||||
uint32_t component_index = 0;
|
||||
for (const Constant* component_const : cc->GetComponents()) {
|
||||
uint32_t component_type_id = 0;
|
||||
if (type_inst && type_inst->opcode() == SpvOpTypeStruct) {
|
||||
if (type_inst && type_inst->opcode() == spv::Op::OpTypeStruct) {
|
||||
component_type_id = type_inst->GetSingleWordInOperand(component_index);
|
||||
} else if (type_inst && type_inst->opcode() == SpvOpTypeArray) {
|
||||
} else if (type_inst && type_inst->opcode() == spv::Op::OpTypeArray) {
|
||||
component_type_id = type_inst->GetSingleWordInOperand(0);
|
||||
}
|
||||
uint32_t id = FindDeclaredConstant(component_const, component_type_id);
|
||||
@@ -381,7 +381,7 @@ std::unique_ptr<Instruction> ConstantManager::CreateCompositeInstruction(
|
||||
}
|
||||
uint32_t type =
|
||||
(type_id == 0) ? context()->get_type_mgr()->GetId(cc->type()) : type_id;
|
||||
return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantComposite, type,
|
||||
return MakeUnique<Instruction>(context(), spv::Op::OpConstantComposite, type,
|
||||
result_id, std::move(operands));
|
||||
}
|
||||
|
||||
@@ -391,6 +391,43 @@ const Constant* ConstantManager::GetConstant(
|
||||
return cst ? RegisterConstant(std::move(cst)) : nullptr;
|
||||
}
|
||||
|
||||
const Constant* ConstantManager::GetNullCompositeConstant(const Type* type) {
|
||||
std::vector<uint32_t> literal_words_or_id;
|
||||
|
||||
if (type->AsVector()) {
|
||||
const Type* element_type = type->AsVector()->element_type();
|
||||
const uint32_t null_id = GetNullConstId(element_type);
|
||||
const uint32_t element_count = type->AsVector()->element_count();
|
||||
for (uint32_t i = 0; i < element_count; i++) {
|
||||
literal_words_or_id.push_back(null_id);
|
||||
}
|
||||
} else if (type->AsMatrix()) {
|
||||
const Type* element_type = type->AsMatrix()->element_type();
|
||||
const uint32_t null_id = GetNullConstId(element_type);
|
||||
const uint32_t element_count = type->AsMatrix()->element_count();
|
||||
for (uint32_t i = 0; i < element_count; i++) {
|
||||
literal_words_or_id.push_back(null_id);
|
||||
}
|
||||
} else if (type->AsStruct()) {
|
||||
// TODO (sfricke-lunarg) add proper struct support
|
||||
return nullptr;
|
||||
} else if (type->AsArray()) {
|
||||
const Type* element_type = type->AsArray()->element_type();
|
||||
const uint32_t null_id = GetNullConstId(element_type);
|
||||
assert(type->AsArray()->length_info().words[0] ==
|
||||
analysis::Array::LengthInfo::kConstant &&
|
||||
"unexpected array length");
|
||||
const uint32_t element_count = type->AsArray()->length_info().words[0];
|
||||
for (uint32_t i = 0; i < element_count; i++) {
|
||||
literal_words_or_id.push_back(null_id);
|
||||
}
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GetConstant(type, literal_words_or_id);
|
||||
}
|
||||
|
||||
const Constant* ConstantManager::GetNumericVectorConstantWithWords(
|
||||
const Vector* type, const std::vector<uint32_t>& literal_words) {
|
||||
const auto* element_type = type->element_type();
|
||||
@@ -445,18 +482,23 @@ const Constant* ConstantManager::GetDoubleConst(double val) {
|
||||
return c;
|
||||
}
|
||||
|
||||
uint32_t ConstantManager::GetSIntConst(int32_t val) {
|
||||
uint32_t ConstantManager::GetSIntConstId(int32_t val) {
|
||||
Type* sint_type = context()->get_type_mgr()->GetSIntType();
|
||||
const Constant* c = GetConstant(sint_type, {static_cast<uint32_t>(val)});
|
||||
return GetDefiningInstruction(c)->result_id();
|
||||
}
|
||||
|
||||
uint32_t ConstantManager::GetUIntConst(uint32_t val) {
|
||||
uint32_t ConstantManager::GetUIntConstId(uint32_t val) {
|
||||
Type* uint_type = context()->get_type_mgr()->GetUIntType();
|
||||
const Constant* c = GetConstant(uint_type, {val});
|
||||
return GetDefiningInstruction(c)->result_id();
|
||||
}
|
||||
|
||||
uint32_t ConstantManager::GetNullConstId(const Type* type) {
|
||||
const Constant* c = GetConstant(type, {});
|
||||
return GetDefiningInstruction(c)->result_id();
|
||||
}
|
||||
|
||||
std::vector<const analysis::Constant*> Constant::GetVectorComponents(
|
||||
analysis::ConstantManager* const_mgr) const {
|
||||
std::vector<const analysis::Constant*> components;
|
||||
|
||||
15
3rdparty/spirv-tools/source/opt/constants.h
vendored
15
3rdparty/spirv-tools/source/opt/constants.h
vendored
@@ -520,6 +520,14 @@ class ConstantManager {
|
||||
literal_words_or_ids.end()));
|
||||
}
|
||||
|
||||
// Takes a type and creates a OpConstantComposite
|
||||
// This allows a
|
||||
// OpConstantNull %composite_type
|
||||
// to become a
|
||||
// OpConstantComposite %composite_type %null %null ... etc
|
||||
// Assumes type is a Composite already, otherwise returns null
|
||||
const Constant* GetNullCompositeConstant(const Type* type);
|
||||
|
||||
// Gets or creates a unique Constant instance of Vector type |type| with
|
||||
// numeric elements and a vector of constant defining words |literal_words|.
|
||||
// If a Constant instance existed already in the constant pool, it returns a
|
||||
@@ -649,10 +657,13 @@ class ConstantManager {
|
||||
const Constant* GetDoubleConst(double val);
|
||||
|
||||
// Returns the id of a 32-bit signed integer constant with value |val|.
|
||||
uint32_t GetSIntConst(int32_t val);
|
||||
uint32_t GetSIntConstId(int32_t val);
|
||||
|
||||
// Returns the id of a 32-bit unsigned integer constant with value |val|.
|
||||
uint32_t GetUIntConst(uint32_t val);
|
||||
uint32_t GetUIntConstId(uint32_t val);
|
||||
|
||||
// Returns the id of a OpConstantNull with type of |type|.
|
||||
uint32_t GetNullConstId(const Type* type);
|
||||
|
||||
private:
|
||||
// Creates a Constant instance with the given type and a vector of constant
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "source/opt/dominator_analysis.h"
|
||||
#include "source/opt/function.h"
|
||||
#include "source/opt/instruction.h"
|
||||
#include "spirv/unified1/spirv.h"
|
||||
|
||||
// Computes the control dependence graph (CDG) using the algorithm in Cytron
|
||||
// 1991, "Efficiently Computing Static Single Assignment Form and the Control
|
||||
@@ -49,8 +48,8 @@ uint32_t ControlDependence::GetConditionID(const CFG& cfg) const {
|
||||
}
|
||||
const BasicBlock* source_bb = cfg.block(source_bb_id());
|
||||
const Instruction* branch = source_bb->terminator();
|
||||
assert((branch->opcode() == SpvOpBranchConditional ||
|
||||
branch->opcode() == SpvOpSwitch) &&
|
||||
assert((branch->opcode() == spv::Op::OpBranchConditional ||
|
||||
branch->opcode() == spv::Op::OpSwitch) &&
|
||||
"invalid control dependence; last instruction must be conditional "
|
||||
"branch or switch");
|
||||
return branch->GetSingleWordInOperand(0);
|
||||
|
||||
@@ -18,19 +18,16 @@
|
||||
|
||||
#include "source/opt/ir_builder.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Indices of operands in SPIR-V instructions
|
||||
static const int kImageSampleDrefIdInIdx = 2;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
// Indices of operands in SPIR-V instructions
|
||||
constexpr int kImageSampleDrefIdInIdx = 2;
|
||||
} // namespace
|
||||
|
||||
bool ConvertToHalfPass::IsArithmetic(Instruction* inst) {
|
||||
return target_ops_core_.count(inst->opcode()) != 0 ||
|
||||
(inst->opcode() == SpvOpExtInst &&
|
||||
(inst->opcode() == spv::Op::OpExtInst &&
|
||||
inst->GetSingleWordInOperand(0) ==
|
||||
context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
|
||||
target_ops_450_.count(inst->GetSingleWordInOperand(1)) != 0);
|
||||
@@ -45,9 +42,11 @@ bool ConvertToHalfPass::IsFloat(Instruction* inst, uint32_t width) {
|
||||
bool ConvertToHalfPass::IsDecoratedRelaxed(Instruction* inst) {
|
||||
uint32_t r_id = inst->result_id();
|
||||
for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
|
||||
if (r_inst->opcode() == SpvOpDecorate &&
|
||||
r_inst->GetSingleWordInOperand(1) == SpvDecorationRelaxedPrecision)
|
||||
if (r_inst->opcode() == spv::Op::OpDecorate &&
|
||||
spv::Decoration(r_inst->GetSingleWordInOperand(1)) ==
|
||||
spv::Decoration::RelaxedPrecision) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,12 +81,12 @@ analysis::Type* ConvertToHalfPass::FloatMatrixType(uint32_t v_cnt,
|
||||
uint32_t ConvertToHalfPass::EquivFloatTypeId(uint32_t ty_id, uint32_t width) {
|
||||
analysis::Type* reg_equiv_ty;
|
||||
Instruction* ty_inst = get_def_use_mgr()->GetDef(ty_id);
|
||||
if (ty_inst->opcode() == SpvOpTypeMatrix)
|
||||
if (ty_inst->opcode() == spv::Op::OpTypeMatrix)
|
||||
reg_equiv_ty = FloatMatrixType(ty_inst->GetSingleWordInOperand(1),
|
||||
ty_inst->GetSingleWordInOperand(0), width);
|
||||
else if (ty_inst->opcode() == SpvOpTypeVector)
|
||||
else if (ty_inst->opcode() == spv::Op::OpTypeVector)
|
||||
reg_equiv_ty = FloatVectorType(ty_inst->GetSingleWordInOperand(1), width);
|
||||
else // SpvOpTypeFloat
|
||||
else // spv::Op::OpTypeFloat
|
||||
reg_equiv_ty = FloatScalarType(width);
|
||||
return context()->get_type_mgr()->GetTypeInstruction(reg_equiv_ty);
|
||||
}
|
||||
@@ -102,18 +101,18 @@ void ConvertToHalfPass::GenConvert(uint32_t* val_idp, uint32_t width,
|
||||
InstructionBuilder builder(
|
||||
context(), inst,
|
||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
||||
if (val_inst->opcode() == SpvOpUndef)
|
||||
cvt_inst = builder.AddNullaryOp(nty_id, SpvOpUndef);
|
||||
if (val_inst->opcode() == spv::Op::OpUndef)
|
||||
cvt_inst = builder.AddNullaryOp(nty_id, spv::Op::OpUndef);
|
||||
else
|
||||
cvt_inst = builder.AddUnaryOp(nty_id, SpvOpFConvert, *val_idp);
|
||||
cvt_inst = builder.AddUnaryOp(nty_id, spv::Op::OpFConvert, *val_idp);
|
||||
*val_idp = cvt_inst->result_id();
|
||||
}
|
||||
|
||||
bool ConvertToHalfPass::MatConvertCleanup(Instruction* inst) {
|
||||
if (inst->opcode() != SpvOpFConvert) return false;
|
||||
if (inst->opcode() != spv::Op::OpFConvert) return false;
|
||||
uint32_t mty_id = inst->type_id();
|
||||
Instruction* mty_inst = get_def_use_mgr()->GetDef(mty_id);
|
||||
if (mty_inst->opcode() != SpvOpTypeMatrix) return false;
|
||||
if (mty_inst->opcode() != spv::Op::OpTypeMatrix) return false;
|
||||
uint32_t vty_id = mty_inst->GetSingleWordInOperand(0);
|
||||
uint32_t v_cnt = mty_inst->GetSingleWordInOperand(1);
|
||||
Instruction* vty_inst = get_def_use_mgr()->GetDef(vty_id);
|
||||
@@ -130,18 +129,18 @@ bool ConvertToHalfPass::MatConvertCleanup(Instruction* inst) {
|
||||
std::vector<Operand> opnds = {};
|
||||
for (uint32_t vidx = 0; vidx < v_cnt; ++vidx) {
|
||||
Instruction* ext_inst = builder.AddIdLiteralOp(
|
||||
orig_vty_id, SpvOpCompositeExtract, orig_mat_id, vidx);
|
||||
orig_vty_id, spv::Op::OpCompositeExtract, orig_mat_id, vidx);
|
||||
Instruction* cvt_inst =
|
||||
builder.AddUnaryOp(vty_id, SpvOpFConvert, ext_inst->result_id());
|
||||
builder.AddUnaryOp(vty_id, spv::Op::OpFConvert, ext_inst->result_id());
|
||||
opnds.push_back({SPV_OPERAND_TYPE_ID, {cvt_inst->result_id()}});
|
||||
}
|
||||
uint32_t mat_id = TakeNextId();
|
||||
std::unique_ptr<Instruction> mat_inst(new Instruction(
|
||||
context(), SpvOpCompositeConstruct, mty_id, mat_id, opnds));
|
||||
context(), spv::Op::OpCompositeConstruct, mty_id, mat_id, opnds));
|
||||
(void)builder.AddInstruction(std::move(mat_inst));
|
||||
context()->ReplaceAllUsesWith(inst->result_id(), mat_id);
|
||||
// Turn original instruction into copy so it is valid.
|
||||
inst->SetOpcode(SpvOpCopyObject);
|
||||
inst->SetOpcode(spv::Op::OpCopyObject);
|
||||
inst->SetResultType(EquivFloatTypeId(mty_id, orig_width));
|
||||
get_def_use_mgr()->AnalyzeInstUse(inst);
|
||||
return true;
|
||||
@@ -150,10 +149,11 @@ bool ConvertToHalfPass::MatConvertCleanup(Instruction* inst) {
|
||||
bool ConvertToHalfPass::RemoveRelaxedDecoration(uint32_t id) {
|
||||
return context()->get_decoration_mgr()->RemoveDecorationsFrom(
|
||||
id, [](const Instruction& dec) {
|
||||
if (dec.opcode() == SpvOpDecorate &&
|
||||
dec.GetSingleWordInOperand(1u) == SpvDecorationRelaxedPrecision)
|
||||
if (dec.opcode() == spv::Op::OpDecorate &&
|
||||
spv::Decoration(dec.GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::RelaxedPrecision) {
|
||||
return true;
|
||||
else
|
||||
} else
|
||||
return false;
|
||||
});
|
||||
}
|
||||
@@ -196,8 +196,8 @@ bool ConvertToHalfPass::ProcessPhi(Instruction* inst, uint32_t from_width,
|
||||
auto insert_before = bp->tail();
|
||||
if (insert_before != bp->begin()) {
|
||||
--insert_before;
|
||||
if (insert_before->opcode() != SpvOpSelectionMerge &&
|
||||
insert_before->opcode() != SpvOpLoopMerge)
|
||||
if (insert_before->opcode() != spv::Op::OpSelectionMerge &&
|
||||
insert_before->opcode() != spv::Op::OpLoopMerge)
|
||||
++insert_before;
|
||||
}
|
||||
GenConvert(prev_idp, to_width, &*insert_before);
|
||||
@@ -229,7 +229,8 @@ bool ConvertToHalfPass::ProcessConvert(Instruction* inst) {
|
||||
// changed to half.
|
||||
uint32_t val_id = inst->GetSingleWordInOperand(0);
|
||||
Instruction* val_inst = get_def_use_mgr()->GetDef(val_id);
|
||||
if (inst->type_id() == val_inst->type_id()) inst->SetOpcode(SpvOpCopyObject);
|
||||
if (inst->type_id() == val_inst->type_id())
|
||||
inst->SetOpcode(spv::Op::OpCopyObject);
|
||||
return true; // modified
|
||||
}
|
||||
|
||||
@@ -251,7 +252,7 @@ bool ConvertToHalfPass::ProcessImageRef(Instruction* inst) {
|
||||
bool ConvertToHalfPass::ProcessDefault(Instruction* inst) {
|
||||
// If non-relaxed instruction has changed operands, need to convert
|
||||
// them back to float32
|
||||
if (inst->opcode() == SpvOpPhi) return ProcessPhi(inst, 16u, 32u);
|
||||
if (inst->opcode() == spv::Op::OpPhi) return ProcessPhi(inst, 16u, 32u);
|
||||
bool modified = false;
|
||||
inst->ForEachInId([&inst, &modified, this](uint32_t* idp) {
|
||||
if (converted_ids_.count(*idp) == 0) return;
|
||||
@@ -269,9 +270,9 @@ bool ConvertToHalfPass::GenHalfInst(Instruction* inst) {
|
||||
bool inst_relaxed = IsRelaxed(inst->result_id());
|
||||
if (IsArithmetic(inst) && inst_relaxed)
|
||||
modified = GenHalfArith(inst);
|
||||
else if (inst->opcode() == SpvOpPhi && inst_relaxed)
|
||||
else if (inst->opcode() == spv::Op::OpPhi && inst_relaxed)
|
||||
modified = ProcessPhi(inst, 32u, 16u);
|
||||
else if (inst->opcode() == SpvOpFConvert)
|
||||
else if (inst->opcode() == spv::Op::OpFConvert)
|
||||
modified = ProcessConvert(inst);
|
||||
else if (image_ops_.count(inst->opcode()) != 0)
|
||||
modified = ProcessImageRef(inst);
|
||||
@@ -350,7 +351,7 @@ Pass::Status ConvertToHalfPass::ProcessImpl() {
|
||||
};
|
||||
bool modified = context()->ProcessReachableCallTree(pfn);
|
||||
// If modified, make sure module has Float16 capability
|
||||
if (modified) context()->AddCapability(SpvCapabilityFloat16);
|
||||
if (modified) context()->AddCapability(spv::Capability::Float16);
|
||||
// Remove all RelaxedPrecision decorations from instructions and globals
|
||||
for (auto c_id : relaxed_ids_set_) {
|
||||
modified |= RemoveRelaxedDecoration(c_id);
|
||||
@@ -371,44 +372,44 @@ Pass::Status ConvertToHalfPass::Process() {
|
||||
|
||||
void ConvertToHalfPass::Initialize() {
|
||||
target_ops_core_ = {
|
||||
SpvOpVectorExtractDynamic,
|
||||
SpvOpVectorInsertDynamic,
|
||||
SpvOpVectorShuffle,
|
||||
SpvOpCompositeConstruct,
|
||||
SpvOpCompositeInsert,
|
||||
SpvOpCompositeExtract,
|
||||
SpvOpCopyObject,
|
||||
SpvOpTranspose,
|
||||
SpvOpConvertSToF,
|
||||
SpvOpConvertUToF,
|
||||
// SpvOpFConvert,
|
||||
// SpvOpQuantizeToF16,
|
||||
SpvOpFNegate,
|
||||
SpvOpFAdd,
|
||||
SpvOpFSub,
|
||||
SpvOpFMul,
|
||||
SpvOpFDiv,
|
||||
SpvOpFMod,
|
||||
SpvOpVectorTimesScalar,
|
||||
SpvOpMatrixTimesScalar,
|
||||
SpvOpVectorTimesMatrix,
|
||||
SpvOpMatrixTimesVector,
|
||||
SpvOpMatrixTimesMatrix,
|
||||
SpvOpOuterProduct,
|
||||
SpvOpDot,
|
||||
SpvOpSelect,
|
||||
SpvOpFOrdEqual,
|
||||
SpvOpFUnordEqual,
|
||||
SpvOpFOrdNotEqual,
|
||||
SpvOpFUnordNotEqual,
|
||||
SpvOpFOrdLessThan,
|
||||
SpvOpFUnordLessThan,
|
||||
SpvOpFOrdGreaterThan,
|
||||
SpvOpFUnordGreaterThan,
|
||||
SpvOpFOrdLessThanEqual,
|
||||
SpvOpFUnordLessThanEqual,
|
||||
SpvOpFOrdGreaterThanEqual,
|
||||
SpvOpFUnordGreaterThanEqual,
|
||||
spv::Op::OpVectorExtractDynamic,
|
||||
spv::Op::OpVectorInsertDynamic,
|
||||
spv::Op::OpVectorShuffle,
|
||||
spv::Op::OpCompositeConstruct,
|
||||
spv::Op::OpCompositeInsert,
|
||||
spv::Op::OpCompositeExtract,
|
||||
spv::Op::OpCopyObject,
|
||||
spv::Op::OpTranspose,
|
||||
spv::Op::OpConvertSToF,
|
||||
spv::Op::OpConvertUToF,
|
||||
// spv::Op::OpFConvert,
|
||||
// spv::Op::OpQuantizeToF16,
|
||||
spv::Op::OpFNegate,
|
||||
spv::Op::OpFAdd,
|
||||
spv::Op::OpFSub,
|
||||
spv::Op::OpFMul,
|
||||
spv::Op::OpFDiv,
|
||||
spv::Op::OpFMod,
|
||||
spv::Op::OpVectorTimesScalar,
|
||||
spv::Op::OpMatrixTimesScalar,
|
||||
spv::Op::OpVectorTimesMatrix,
|
||||
spv::Op::OpMatrixTimesVector,
|
||||
spv::Op::OpMatrixTimesMatrix,
|
||||
spv::Op::OpOuterProduct,
|
||||
spv::Op::OpDot,
|
||||
spv::Op::OpSelect,
|
||||
spv::Op::OpFOrdEqual,
|
||||
spv::Op::OpFUnordEqual,
|
||||
spv::Op::OpFOrdNotEqual,
|
||||
spv::Op::OpFUnordNotEqual,
|
||||
spv::Op::OpFOrdLessThan,
|
||||
spv::Op::OpFUnordLessThan,
|
||||
spv::Op::OpFOrdGreaterThan,
|
||||
spv::Op::OpFUnordGreaterThan,
|
||||
spv::Op::OpFOrdLessThanEqual,
|
||||
spv::Op::OpFUnordLessThanEqual,
|
||||
spv::Op::OpFOrdGreaterThanEqual,
|
||||
spv::Op::OpFUnordGreaterThanEqual,
|
||||
};
|
||||
target_ops_450_ = {
|
||||
GLSLstd450Round, GLSLstd450RoundEven, GLSLstd450Trunc, GLSLstd450FAbs,
|
||||
@@ -427,53 +428,53 @@ void ConvertToHalfPass::Initialize() {
|
||||
GLSLstd450Ldexp, GLSLstd450Length, GLSLstd450Distance, GLSLstd450Cross,
|
||||
GLSLstd450Normalize, GLSLstd450FaceForward, GLSLstd450Reflect,
|
||||
GLSLstd450Refract, GLSLstd450NMin, GLSLstd450NMax, GLSLstd450NClamp};
|
||||
image_ops_ = {SpvOpImageSampleImplicitLod,
|
||||
SpvOpImageSampleExplicitLod,
|
||||
SpvOpImageSampleDrefImplicitLod,
|
||||
SpvOpImageSampleDrefExplicitLod,
|
||||
SpvOpImageSampleProjImplicitLod,
|
||||
SpvOpImageSampleProjExplicitLod,
|
||||
SpvOpImageSampleProjDrefImplicitLod,
|
||||
SpvOpImageSampleProjDrefExplicitLod,
|
||||
SpvOpImageFetch,
|
||||
SpvOpImageGather,
|
||||
SpvOpImageDrefGather,
|
||||
SpvOpImageRead,
|
||||
SpvOpImageSparseSampleImplicitLod,
|
||||
SpvOpImageSparseSampleExplicitLod,
|
||||
SpvOpImageSparseSampleDrefImplicitLod,
|
||||
SpvOpImageSparseSampleDrefExplicitLod,
|
||||
SpvOpImageSparseSampleProjImplicitLod,
|
||||
SpvOpImageSparseSampleProjExplicitLod,
|
||||
SpvOpImageSparseSampleProjDrefImplicitLod,
|
||||
SpvOpImageSparseSampleProjDrefExplicitLod,
|
||||
SpvOpImageSparseFetch,
|
||||
SpvOpImageSparseGather,
|
||||
SpvOpImageSparseDrefGather,
|
||||
SpvOpImageSparseTexelsResident,
|
||||
SpvOpImageSparseRead};
|
||||
image_ops_ = {spv::Op::OpImageSampleImplicitLod,
|
||||
spv::Op::OpImageSampleExplicitLod,
|
||||
spv::Op::OpImageSampleDrefImplicitLod,
|
||||
spv::Op::OpImageSampleDrefExplicitLod,
|
||||
spv::Op::OpImageSampleProjImplicitLod,
|
||||
spv::Op::OpImageSampleProjExplicitLod,
|
||||
spv::Op::OpImageSampleProjDrefImplicitLod,
|
||||
spv::Op::OpImageSampleProjDrefExplicitLod,
|
||||
spv::Op::OpImageFetch,
|
||||
spv::Op::OpImageGather,
|
||||
spv::Op::OpImageDrefGather,
|
||||
spv::Op::OpImageRead,
|
||||
spv::Op::OpImageSparseSampleImplicitLod,
|
||||
spv::Op::OpImageSparseSampleExplicitLod,
|
||||
spv::Op::OpImageSparseSampleDrefImplicitLod,
|
||||
spv::Op::OpImageSparseSampleDrefExplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjImplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjExplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjDrefImplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjDrefExplicitLod,
|
||||
spv::Op::OpImageSparseFetch,
|
||||
spv::Op::OpImageSparseGather,
|
||||
spv::Op::OpImageSparseDrefGather,
|
||||
spv::Op::OpImageSparseTexelsResident,
|
||||
spv::Op::OpImageSparseRead};
|
||||
dref_image_ops_ = {
|
||||
SpvOpImageSampleDrefImplicitLod,
|
||||
SpvOpImageSampleDrefExplicitLod,
|
||||
SpvOpImageSampleProjDrefImplicitLod,
|
||||
SpvOpImageSampleProjDrefExplicitLod,
|
||||
SpvOpImageDrefGather,
|
||||
SpvOpImageSparseSampleDrefImplicitLod,
|
||||
SpvOpImageSparseSampleDrefExplicitLod,
|
||||
SpvOpImageSparseSampleProjDrefImplicitLod,
|
||||
SpvOpImageSparseSampleProjDrefExplicitLod,
|
||||
SpvOpImageSparseDrefGather,
|
||||
spv::Op::OpImageSampleDrefImplicitLod,
|
||||
spv::Op::OpImageSampleDrefExplicitLod,
|
||||
spv::Op::OpImageSampleProjDrefImplicitLod,
|
||||
spv::Op::OpImageSampleProjDrefExplicitLod,
|
||||
spv::Op::OpImageDrefGather,
|
||||
spv::Op::OpImageSparseSampleDrefImplicitLod,
|
||||
spv::Op::OpImageSparseSampleDrefExplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjDrefImplicitLod,
|
||||
spv::Op::OpImageSparseSampleProjDrefExplicitLod,
|
||||
spv::Op::OpImageSparseDrefGather,
|
||||
};
|
||||
closure_ops_ = {
|
||||
SpvOpVectorExtractDynamic,
|
||||
SpvOpVectorInsertDynamic,
|
||||
SpvOpVectorShuffle,
|
||||
SpvOpCompositeConstruct,
|
||||
SpvOpCompositeInsert,
|
||||
SpvOpCompositeExtract,
|
||||
SpvOpCopyObject,
|
||||
SpvOpTranspose,
|
||||
SpvOpPhi,
|
||||
spv::Op::OpVectorExtractDynamic,
|
||||
spv::Op::OpVectorInsertDynamic,
|
||||
spv::Op::OpVectorShuffle,
|
||||
spv::Op::OpCompositeConstruct,
|
||||
spv::Op::OpCompositeInsert,
|
||||
spv::Op::OpCompositeExtract,
|
||||
spv::Op::OpCopyObject,
|
||||
spv::Op::OpTranspose,
|
||||
spv::Op::OpPhi,
|
||||
};
|
||||
relaxed_ids_set_.clear();
|
||||
converted_ids_.clear();
|
||||
|
||||
@@ -120,20 +120,26 @@ class ConvertToHalfPass : public Pass {
|
||||
// Initialize state for converting to half
|
||||
void Initialize();
|
||||
|
||||
struct hasher {
|
||||
size_t operator()(const spv::Op& op) const noexcept {
|
||||
return std::hash<uint32_t>()(uint32_t(op));
|
||||
}
|
||||
};
|
||||
|
||||
// Set of core operations to be processed
|
||||
std::unordered_set<uint32_t> target_ops_core_;
|
||||
std::unordered_set<spv::Op, hasher> target_ops_core_;
|
||||
|
||||
// Set of 450 extension operations to be processed
|
||||
std::unordered_set<uint32_t> target_ops_450_;
|
||||
|
||||
// Set of sample operations
|
||||
std::unordered_set<uint32_t> image_ops_;
|
||||
std::unordered_set<spv::Op, hasher> image_ops_;
|
||||
|
||||
// Set of dref sample operations
|
||||
std::unordered_set<uint32_t> dref_image_ops_;
|
||||
std::unordered_set<spv::Op, hasher> dref_image_ops_;
|
||||
|
||||
// Set of dref sample operations
|
||||
std::unordered_set<uint32_t> closure_ops_;
|
||||
std::unordered_set<spv::Op, hasher> closure_ops_;
|
||||
|
||||
// Set of ids of all relaxed instructions
|
||||
std::unordered_set<uint32_t> relaxed_ids_set_;
|
||||
|
||||
@@ -70,7 +70,7 @@ uint32_t GetImageTypeOfSampledImage(analysis::TypeManager* type_mgr,
|
||||
Instruction* GetNonCopyObjectDef(analysis::DefUseManager* def_use_mgr,
|
||||
uint32_t inst_id) {
|
||||
Instruction* inst = def_use_mgr->GetDef(inst_id);
|
||||
while (inst->opcode() == SpvOpCopyObject) {
|
||||
while (inst->opcode() == spv::Op::OpCopyObject) {
|
||||
inst_id = inst->GetSingleWordInOperand(0u);
|
||||
inst = def_use_mgr->GetDef(inst_id);
|
||||
}
|
||||
@@ -87,8 +87,9 @@ bool ConvertToSampledImagePass::GetDescriptorSetBinding(
|
||||
bool found_binding_to_convert = false;
|
||||
for (auto decorate :
|
||||
decoration_manager->GetDecorationsFor(inst.result_id(), false)) {
|
||||
uint32_t decoration = decorate->GetSingleWordInOperand(1u);
|
||||
if (decoration == SpvDecorationDescriptorSet) {
|
||||
spv::Decoration decoration =
|
||||
spv::Decoration(decorate->GetSingleWordInOperand(1u));
|
||||
if (decoration == spv::Decoration::DescriptorSet) {
|
||||
if (found_descriptor_set_to_convert) {
|
||||
assert(false && "A resource has two OpDecorate for the descriptor set");
|
||||
return false;
|
||||
@@ -96,7 +97,7 @@ bool ConvertToSampledImagePass::GetDescriptorSetBinding(
|
||||
descriptor_set_binding->descriptor_set =
|
||||
decorate->GetSingleWordInOperand(2u);
|
||||
found_descriptor_set_to_convert = true;
|
||||
} else if (decoration == SpvDecorationBinding) {
|
||||
} else if (decoration == spv::Decoration::Binding) {
|
||||
if (found_binding_to_convert) {
|
||||
assert(false && "A resource has two OpDecorate for the binding");
|
||||
return false;
|
||||
@@ -116,7 +117,7 @@ bool ConvertToSampledImagePass::ShouldResourceBeConverted(
|
||||
|
||||
const analysis::Type* ConvertToSampledImagePass::GetVariableType(
|
||||
const Instruction& variable) const {
|
||||
if (variable.opcode() != SpvOpVariable) return nullptr;
|
||||
if (variable.opcode() != spv::Op::OpVariable) return nullptr;
|
||||
auto* type = context()->get_type_mgr()->GetType(variable.type_id());
|
||||
auto* pointer_type = type->AsPointer();
|
||||
if (!pointer_type) return nullptr;
|
||||
@@ -124,12 +125,12 @@ const analysis::Type* ConvertToSampledImagePass::GetVariableType(
|
||||
return pointer_type->pointee_type();
|
||||
}
|
||||
|
||||
SpvStorageClass ConvertToSampledImagePass::GetStorageClass(
|
||||
spv::StorageClass ConvertToSampledImagePass::GetStorageClass(
|
||||
const Instruction& variable) const {
|
||||
assert(variable.opcode() == SpvOpVariable);
|
||||
assert(variable.opcode() == spv::Op::OpVariable);
|
||||
auto* type = context()->get_type_mgr()->GetType(variable.type_id());
|
||||
auto* pointer_type = type->AsPointer();
|
||||
if (!pointer_type) return SpvStorageClassMax;
|
||||
if (!pointer_type) return spv::StorageClass::Max;
|
||||
|
||||
return pointer_type->storage_class();
|
||||
}
|
||||
@@ -205,12 +206,12 @@ Pass::Status ConvertToSampledImagePass::Process() {
|
||||
|
||||
void ConvertToSampledImagePass::FindUses(const Instruction* inst,
|
||||
std::vector<Instruction*>* uses,
|
||||
uint32_t user_opcode) const {
|
||||
spv::Op user_opcode) const {
|
||||
auto* def_use_mgr = context()->get_def_use_mgr();
|
||||
def_use_mgr->ForEachUser(inst, [uses, user_opcode, this](Instruction* user) {
|
||||
if (user->opcode() == user_opcode) {
|
||||
uses->push_back(user);
|
||||
} else if (user->opcode() == SpvOpCopyObject) {
|
||||
} else if (user->opcode() == spv::Op::OpCopyObject) {
|
||||
FindUses(user, uses, user_opcode);
|
||||
}
|
||||
});
|
||||
@@ -221,21 +222,21 @@ void ConvertToSampledImagePass::FindUsesOfImage(
|
||||
auto* def_use_mgr = context()->get_def_use_mgr();
|
||||
def_use_mgr->ForEachUser(image, [uses, this](Instruction* user) {
|
||||
switch (user->opcode()) {
|
||||
case SpvOpImageFetch:
|
||||
case SpvOpImageRead:
|
||||
case SpvOpImageWrite:
|
||||
case SpvOpImageQueryFormat:
|
||||
case SpvOpImageQueryOrder:
|
||||
case SpvOpImageQuerySizeLod:
|
||||
case SpvOpImageQuerySize:
|
||||
case SpvOpImageQueryLevels:
|
||||
case SpvOpImageQuerySamples:
|
||||
case SpvOpImageSparseFetch:
|
||||
case spv::Op::OpImageFetch:
|
||||
case spv::Op::OpImageRead:
|
||||
case spv::Op::OpImageWrite:
|
||||
case spv::Op::OpImageQueryFormat:
|
||||
case spv::Op::OpImageQueryOrder:
|
||||
case spv::Op::OpImageQuerySizeLod:
|
||||
case spv::Op::OpImageQuerySize:
|
||||
case spv::Op::OpImageQueryLevels:
|
||||
case spv::Op::OpImageQuerySamples:
|
||||
case spv::Op::OpImageSparseFetch:
|
||||
uses->push_back(user);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (user->opcode() == SpvOpCopyObject) {
|
||||
if (user->opcode() == spv::Op::OpCopyObject) {
|
||||
FindUsesOfImage(user, uses);
|
||||
}
|
||||
});
|
||||
@@ -248,7 +249,7 @@ Instruction* ConvertToSampledImagePass::CreateImageExtraction(
|
||||
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
|
||||
return builder.AddUnaryOp(
|
||||
GetImageTypeOfSampledImage(context()->get_type_mgr(), sampled_image),
|
||||
SpvOpImage, sampled_image->result_id());
|
||||
spv::Op::OpImage, sampled_image->result_id());
|
||||
}
|
||||
|
||||
uint32_t ConvertToSampledImagePass::GetSampledImageTypeForImage(
|
||||
@@ -284,7 +285,7 @@ bool ConvertToSampledImagePass::
|
||||
auto* def_use_mgr = context()->get_def_use_mgr();
|
||||
uint32_t sampler_id = sampled_image_inst->GetSingleWordInOperand(1u);
|
||||
auto* sampler_load = def_use_mgr->GetDef(sampler_id);
|
||||
if (sampler_load->opcode() != SpvOpLoad) return false;
|
||||
if (sampler_load->opcode() != spv::Op::OpLoad) return false;
|
||||
auto* sampler = def_use_mgr->GetDef(sampler_load->GetSingleWordInOperand(0u));
|
||||
DescriptorSetAndBinding sampler_descriptor_set_binding;
|
||||
return GetDescriptorSetBinding(*sampler, &sampler_descriptor_set_binding) &&
|
||||
@@ -295,7 +296,7 @@ void ConvertToSampledImagePass::UpdateSampledImageUses(
|
||||
Instruction* image_load, Instruction* image_extraction,
|
||||
const DescriptorSetAndBinding& image_descriptor_set_binding) {
|
||||
std::vector<Instruction*> sampled_image_users;
|
||||
FindUses(image_load, &sampled_image_users, SpvOpSampledImage);
|
||||
FindUses(image_load, &sampled_image_users, spv::Op::OpSampledImage);
|
||||
|
||||
auto* def_use_mgr = context()->get_def_use_mgr();
|
||||
for (auto* sampled_image_inst : sampled_image_users) {
|
||||
@@ -328,7 +329,7 @@ bool ConvertToSampledImagePass::ConvertImageVariableToSampledImage(
|
||||
context()->get_type_mgr()->GetType(sampled_image_type_id);
|
||||
if (sampled_image_type == nullptr) return false;
|
||||
auto storage_class = GetStorageClass(*image_variable);
|
||||
if (storage_class == SpvStorageClassMax) return false;
|
||||
if (storage_class == spv::StorageClass::Max) return false;
|
||||
analysis::Pointer sampled_image_pointer(sampled_image_type, storage_class);
|
||||
|
||||
// Make sure |image_variable| is behind its type i.e., avoid the forward
|
||||
@@ -343,7 +344,7 @@ Pass::Status ConvertToSampledImagePass::UpdateImageVariableToSampledImage(
|
||||
Instruction* image_variable,
|
||||
const DescriptorSetAndBinding& descriptor_set_binding) {
|
||||
std::vector<Instruction*> image_variable_loads;
|
||||
FindUses(image_variable, &image_variable_loads, SpvOpLoad);
|
||||
FindUses(image_variable, &image_variable_loads, spv::Op::OpLoad);
|
||||
if (image_variable_loads.empty()) return Status::SuccessWithoutChange;
|
||||
|
||||
const uint32_t sampled_image_type_id =
|
||||
@@ -364,14 +365,14 @@ Pass::Status ConvertToSampledImagePass::UpdateImageVariableToSampledImage(
|
||||
|
||||
bool ConvertToSampledImagePass::DoesSampledImageReferenceImage(
|
||||
Instruction* sampled_image_inst, Instruction* image_variable) {
|
||||
if (sampled_image_inst->opcode() != SpvOpSampledImage) return false;
|
||||
if (sampled_image_inst->opcode() != spv::Op::OpSampledImage) return false;
|
||||
auto* def_use_mgr = context()->get_def_use_mgr();
|
||||
auto* image_load = GetNonCopyObjectDef(
|
||||
def_use_mgr, sampled_image_inst->GetSingleWordInOperand(0u));
|
||||
if (image_load->opcode() != SpvOpLoad) return false;
|
||||
if (image_load->opcode() != spv::Op::OpLoad) return false;
|
||||
auto* image =
|
||||
GetNonCopyObjectDef(def_use_mgr, image_load->GetSingleWordInOperand(0u));
|
||||
return image->opcode() == SpvOpVariable &&
|
||||
return image->opcode() == spv::Op::OpVariable &&
|
||||
image->result_id() == image_variable->result_id();
|
||||
}
|
||||
|
||||
@@ -381,10 +382,10 @@ Pass::Status ConvertToSampledImagePass::CheckUsesOfSamplerVariable(
|
||||
if (image_to_be_combined_with == nullptr) return Status::Failure;
|
||||
|
||||
std::vector<Instruction*> sampler_variable_loads;
|
||||
FindUses(sampler_variable, &sampler_variable_loads, SpvOpLoad);
|
||||
FindUses(sampler_variable, &sampler_variable_loads, spv::Op::OpLoad);
|
||||
for (auto* load : sampler_variable_loads) {
|
||||
std::vector<Instruction*> sampled_image_users;
|
||||
FindUses(load, &sampled_image_users, SpvOpSampledImage);
|
||||
FindUses(load, &sampled_image_users, spv::Op::OpSampledImage);
|
||||
for (auto* sampled_image_inst : sampled_image_users) {
|
||||
if (!DoesSampledImageReferenceImage(sampled_image_inst,
|
||||
image_to_be_combined_with)) {
|
||||
|
||||
@@ -120,13 +120,13 @@ class ConvertToSampledImagePass : public Pass {
|
||||
const analysis::Type* GetVariableType(const Instruction& variable) const;
|
||||
|
||||
// Returns the storage class of |variable|.
|
||||
SpvStorageClass GetStorageClass(const Instruction& variable) const;
|
||||
spv::StorageClass GetStorageClass(const Instruction& variable) const;
|
||||
|
||||
// Finds |inst|'s users whose opcode is |user_opcode| or users of OpCopyObject
|
||||
// instructions of |inst| whose opcode is |user_opcode| and puts them in
|
||||
// |uses|.
|
||||
void FindUses(const Instruction* inst, std::vector<Instruction*>* uses,
|
||||
uint32_t user_opcode) const;
|
||||
spv::Op user_opcode) const;
|
||||
|
||||
// Finds OpImage* instructions using |image| or OpCopyObject instructions that
|
||||
// copy |image| and puts them in |uses|.
|
||||
|
||||
108
3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp
vendored
108
3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp
vendored
@@ -22,12 +22,12 @@ namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
|
||||
const uint32_t kLoadPointerInOperand = 0;
|
||||
const uint32_t kStorePointerInOperand = 0;
|
||||
const uint32_t kStoreObjectInOperand = 1;
|
||||
const uint32_t kCompositeExtractObjectInOperand = 0;
|
||||
const uint32_t kTypePointerStorageClassInIdx = 0;
|
||||
const uint32_t kTypePointerPointeeInIdx = 1;
|
||||
constexpr uint32_t kLoadPointerInOperand = 0;
|
||||
constexpr uint32_t kStorePointerInOperand = 0;
|
||||
constexpr uint32_t kStoreObjectInOperand = 1;
|
||||
constexpr uint32_t kCompositeExtractObjectInOperand = 0;
|
||||
constexpr uint32_t kTypePointerStorageClassInIdx = 0;
|
||||
constexpr uint32_t kTypePointerPointeeInIdx = 1;
|
||||
|
||||
bool IsDebugDeclareOrValue(Instruction* di) {
|
||||
auto dbg_opcode = di->GetCommonDebugOpcode();
|
||||
@@ -46,8 +46,8 @@ Pass::Status CopyPropagateArrays::Process() {
|
||||
|
||||
BasicBlock* entry_bb = &*function.begin();
|
||||
|
||||
for (auto var_inst = entry_bb->begin(); var_inst->opcode() == SpvOpVariable;
|
||||
++var_inst) {
|
||||
for (auto var_inst = entry_bb->begin();
|
||||
var_inst->opcode() == spv::Op::OpVariable; ++var_inst) {
|
||||
if (!IsPointerToArrayType(var_inst->type_id())) {
|
||||
continue;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ Pass::Status CopyPropagateArrays::Process() {
|
||||
std::unique_ptr<CopyPropagateArrays::MemoryObject>
|
||||
CopyPropagateArrays::FindSourceObjectIfPossible(Instruction* var_inst,
|
||||
Instruction* store_inst) {
|
||||
assert(var_inst->opcode() == SpvOpVariable && "Expecting a variable.");
|
||||
assert(var_inst->opcode() == spv::Op::OpVariable && "Expecting a variable.");
|
||||
|
||||
// Check that the variable is a composite object where |store_inst|
|
||||
// dominates all of its loads.
|
||||
@@ -114,7 +114,7 @@ Instruction* CopyPropagateArrays::FindStoreInstruction(
|
||||
Instruction* store_inst = nullptr;
|
||||
get_def_use_mgr()->WhileEachUser(
|
||||
var_inst, [&store_inst, var_inst](Instruction* use) {
|
||||
if (use->opcode() == SpvOpStore &&
|
||||
if (use->opcode() == spv::Op::OpStore &&
|
||||
use->GetSingleWordInOperand(kStorePointerInOperand) ==
|
||||
var_inst->result_id()) {
|
||||
if (store_inst == nullptr) {
|
||||
@@ -132,7 +132,7 @@ Instruction* CopyPropagateArrays::FindStoreInstruction(
|
||||
void CopyPropagateArrays::PropagateObject(Instruction* var_inst,
|
||||
MemoryObject* source,
|
||||
Instruction* insertion_point) {
|
||||
assert(var_inst->opcode() == SpvOpVariable &&
|
||||
assert(var_inst->opcode() == spv::Op::OpVariable &&
|
||||
"This function propagates variables.");
|
||||
|
||||
Instruction* new_access_chain = BuildNewAccessChain(insertion_point, source);
|
||||
@@ -166,17 +166,17 @@ Instruction* CopyPropagateArrays::BuildNewAccessChain(
|
||||
|
||||
bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) {
|
||||
return get_def_use_mgr()->WhileEachUser(ptr_inst, [this](Instruction* use) {
|
||||
if (use->opcode() == SpvOpLoad) {
|
||||
if (use->opcode() == spv::Op::OpLoad) {
|
||||
return true;
|
||||
} else if (use->opcode() == SpvOpAccessChain) {
|
||||
} else if (use->opcode() == spv::Op::OpAccessChain) {
|
||||
return HasNoStores(use);
|
||||
} else if (use->IsDecoration() || use->opcode() == SpvOpName) {
|
||||
} else if (use->IsDecoration() || use->opcode() == spv::Op::OpName) {
|
||||
return true;
|
||||
} else if (use->opcode() == SpvOpStore) {
|
||||
} else if (use->opcode() == spv::Op::OpStore) {
|
||||
return false;
|
||||
} else if (use->opcode() == SpvOpImageTexelPointer) {
|
||||
} else if (use->opcode() == spv::Op::OpImageTexelPointer) {
|
||||
return true;
|
||||
} else if (use->opcode() == SpvOpEntryPoint) {
|
||||
} else if (use->opcode() == spv::Op::OpEntryPoint) {
|
||||
return true;
|
||||
}
|
||||
// Some other instruction. Be conservative.
|
||||
@@ -193,19 +193,19 @@ bool CopyPropagateArrays::HasValidReferencesOnly(Instruction* ptr_inst,
|
||||
return get_def_use_mgr()->WhileEachUser(
|
||||
ptr_inst,
|
||||
[this, store_inst, dominator_analysis, ptr_inst](Instruction* use) {
|
||||
if (use->opcode() == SpvOpLoad ||
|
||||
use->opcode() == SpvOpImageTexelPointer) {
|
||||
if (use->opcode() == spv::Op::OpLoad ||
|
||||
use->opcode() == spv::Op::OpImageTexelPointer) {
|
||||
// TODO: If there are many load in the same BB as |store_inst| the
|
||||
// time to do the multiple traverses can add up. Consider collecting
|
||||
// those loads and doing a single traversal.
|
||||
return dominator_analysis->Dominates(store_inst, use);
|
||||
} else if (use->opcode() == SpvOpAccessChain) {
|
||||
} else if (use->opcode() == spv::Op::OpAccessChain) {
|
||||
return HasValidReferencesOnly(use, store_inst);
|
||||
} else if (use->IsDecoration() || use->opcode() == SpvOpName) {
|
||||
} else if (use->IsDecoration() || use->opcode() == spv::Op::OpName) {
|
||||
return true;
|
||||
} else if (use->opcode() == SpvOpStore) {
|
||||
} else if (use->opcode() == spv::Op::OpStore) {
|
||||
// If we are storing to part of the object it is not an candidate.
|
||||
return ptr_inst->opcode() == SpvOpVariable &&
|
||||
return ptr_inst->opcode() == spv::Op::OpVariable &&
|
||||
store_inst->GetSingleWordInOperand(kStorePointerInOperand) ==
|
||||
ptr_inst->result_id();
|
||||
} else if (IsDebugDeclareOrValue(use)) {
|
||||
@@ -221,15 +221,15 @@ CopyPropagateArrays::GetSourceObjectIfAny(uint32_t result) {
|
||||
Instruction* result_inst = context()->get_def_use_mgr()->GetDef(result);
|
||||
|
||||
switch (result_inst->opcode()) {
|
||||
case SpvOpLoad:
|
||||
case spv::Op::OpLoad:
|
||||
return BuildMemoryObjectFromLoad(result_inst);
|
||||
case SpvOpCompositeExtract:
|
||||
case spv::Op::OpCompositeExtract:
|
||||
return BuildMemoryObjectFromExtract(result_inst);
|
||||
case SpvOpCompositeConstruct:
|
||||
case spv::Op::OpCompositeConstruct:
|
||||
return BuildMemoryObjectFromCompositeConstruct(result_inst);
|
||||
case SpvOpCopyObject:
|
||||
case spv::Op::OpCopyObject:
|
||||
return GetSourceObjectIfAny(result_inst->GetSingleWordInOperand(0));
|
||||
case SpvOpCompositeInsert:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
return BuildMemoryObjectFromInsert(result_inst);
|
||||
default:
|
||||
return nullptr;
|
||||
@@ -251,7 +251,7 @@ CopyPropagateArrays::BuildMemoryObjectFromLoad(Instruction* load_inst) {
|
||||
//
|
||||
// It is built in reverse order because the different |OpAccessChain|
|
||||
// instructions are visited in reverse order from which they are applied.
|
||||
while (current_inst->opcode() == SpvOpAccessChain) {
|
||||
while (current_inst->opcode() == spv::Op::OpAccessChain) {
|
||||
for (uint32_t i = current_inst->NumInOperands() - 1; i >= 1; --i) {
|
||||
uint32_t element_index_id = current_inst->GetSingleWordInOperand(i);
|
||||
components_in_reverse.push_back(element_index_id);
|
||||
@@ -263,7 +263,7 @@ CopyPropagateArrays::BuildMemoryObjectFromLoad(Instruction* load_inst) {
|
||||
// instruction followed by a series of |OpAccessChain| instructions, then
|
||||
// return |nullptr| because we cannot identify the owner or access chain
|
||||
// exactly.
|
||||
if (current_inst->opcode() != SpvOpVariable) {
|
||||
if (current_inst->opcode() != spv::Op::OpVariable) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ CopyPropagateArrays::BuildMemoryObjectFromLoad(Instruction* load_inst) {
|
||||
|
||||
std::unique_ptr<CopyPropagateArrays::MemoryObject>
|
||||
CopyPropagateArrays::BuildMemoryObjectFromExtract(Instruction* extract_inst) {
|
||||
assert(extract_inst->opcode() == SpvOpCompositeExtract &&
|
||||
assert(extract_inst->opcode() == spv::Op::OpCompositeExtract &&
|
||||
"Expecting an OpCompositeExtract instruction.");
|
||||
std::unique_ptr<MemoryObject> result = GetSourceObjectIfAny(
|
||||
extract_inst->GetSingleWordInOperand(kCompositeExtractObjectInOperand));
|
||||
@@ -297,7 +297,7 @@ CopyPropagateArrays::BuildMemoryObjectFromExtract(Instruction* extract_inst) {
|
||||
std::unique_ptr<CopyPropagateArrays::MemoryObject>
|
||||
CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct(
|
||||
Instruction* conststruct_inst) {
|
||||
assert(conststruct_inst->opcode() == SpvOpCompositeConstruct &&
|
||||
assert(conststruct_inst->opcode() == spv::Op::OpCompositeConstruct &&
|
||||
"Expecting an OpCompositeConstruct instruction.");
|
||||
|
||||
// If every operand in the instruction are part of the same memory object, and
|
||||
@@ -352,7 +352,7 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct(
|
||||
|
||||
std::unique_ptr<CopyPropagateArrays::MemoryObject>
|
||||
CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) {
|
||||
assert(insert_inst->opcode() == SpvOpCompositeInsert &&
|
||||
assert(insert_inst->opcode() == spv::Op::OpCompositeInsert &&
|
||||
"Expecting an OpCompositeInsert instruction.");
|
||||
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
@@ -407,7 +407,7 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) {
|
||||
Instruction* current_insert =
|
||||
def_use_mgr->GetDef(insert_inst->GetSingleWordInOperand(1));
|
||||
for (uint32_t i = number_of_elements - 1; i > 0; --i) {
|
||||
if (current_insert->opcode() != SpvOpCompositeInsert) {
|
||||
if (current_insert->opcode() != spv::Op::OpCompositeInsert) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst,
|
||||
if (IsDebugDeclareOrValue(use)) return true;
|
||||
|
||||
switch (use->opcode()) {
|
||||
case SpvOpLoad: {
|
||||
case spv::Op::OpLoad: {
|
||||
analysis::Pointer* pointer_type = type->AsPointer();
|
||||
uint32_t new_type_id = type_mgr->GetId(pointer_type->pointee_type());
|
||||
|
||||
@@ -509,7 +509,7 @@ bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SpvOpAccessChain: {
|
||||
case spv::Op::OpAccessChain: {
|
||||
analysis::Pointer* pointer_type = type->AsPointer();
|
||||
const analysis::Type* pointee_type = pointer_type->pointee_type();
|
||||
|
||||
@@ -547,7 +547,7 @@ bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SpvOpCompositeExtract: {
|
||||
case spv::Op::OpCompositeExtract: {
|
||||
std::vector<uint32_t> access_chain;
|
||||
for (uint32_t i = 1; i < use->NumInOperands(); ++i) {
|
||||
access_chain.push_back(use->GetSingleWordInOperand(i));
|
||||
@@ -565,13 +565,13 @@ bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SpvOpStore:
|
||||
case spv::Op::OpStore:
|
||||
// If needed, we can create an element-by-element copy to change the
|
||||
// type of the value being stored. This way we can always handled
|
||||
// stores.
|
||||
return true;
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpName:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
case spv::Op::OpName:
|
||||
return true;
|
||||
default:
|
||||
return use->IsDecoration();
|
||||
@@ -598,8 +598,8 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
|
||||
if (use->IsCommonDebugInstr()) {
|
||||
switch (use->GetCommonDebugOpcode()) {
|
||||
case CommonDebugInfoDebugDeclare: {
|
||||
if (new_ptr_inst->opcode() == SpvOpVariable ||
|
||||
new_ptr_inst->opcode() == SpvOpFunctionParameter) {
|
||||
if (new_ptr_inst->opcode() == spv::Op::OpVariable ||
|
||||
new_ptr_inst->opcode() == spv::Op::OpFunctionParameter) {
|
||||
context()->ForgetUses(use);
|
||||
use->SetOperand(index, {new_ptr_inst->result_id()});
|
||||
context()->AnalyzeUses(use);
|
||||
@@ -640,7 +640,7 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
|
||||
}
|
||||
|
||||
switch (use->opcode()) {
|
||||
case SpvOpLoad: {
|
||||
case spv::Op::OpLoad: {
|
||||
// Replace the actual use.
|
||||
context()->ForgetUses(use);
|
||||
use->SetOperand(index, {new_ptr_inst->result_id()});
|
||||
@@ -658,7 +658,7 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
|
||||
context()->AnalyzeUses(use);
|
||||
}
|
||||
} break;
|
||||
case SpvOpAccessChain: {
|
||||
case spv::Op::OpAccessChain: {
|
||||
// Update the actual use.
|
||||
context()->ForgetUses(use);
|
||||
use->SetOperand(index, {new_ptr_inst->result_id()});
|
||||
@@ -685,7 +685,7 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
|
||||
pointer_type_inst->GetSingleWordInOperand(kTypePointerPointeeInIdx),
|
||||
access_chain);
|
||||
|
||||
SpvStorageClass storage_class = static_cast<SpvStorageClass>(
|
||||
spv::StorageClass storage_class = static_cast<spv::StorageClass>(
|
||||
pointer_type_inst->GetSingleWordInOperand(
|
||||
kTypePointerStorageClassInIdx));
|
||||
|
||||
@@ -700,7 +700,7 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
|
||||
context()->AnalyzeUses(use);
|
||||
}
|
||||
} break;
|
||||
case SpvOpCompositeExtract: {
|
||||
case spv::Op::OpCompositeExtract: {
|
||||
// Update the actual use.
|
||||
context()->ForgetUses(use);
|
||||
use->SetOperand(index, {new_ptr_inst->result_id()});
|
||||
@@ -721,7 +721,7 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
|
||||
context()->AnalyzeUses(use);
|
||||
}
|
||||
} break;
|
||||
case SpvOpStore:
|
||||
case spv::Op::OpStore:
|
||||
// If the use is the pointer, then it is the single store to that
|
||||
// variable. We do not want to replace it. Instead, it will become
|
||||
// dead after all of the loads are removed, and ADCE will get rid of it.
|
||||
@@ -744,11 +744,11 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst,
|
||||
context()->AnalyzeUses(use);
|
||||
}
|
||||
break;
|
||||
case SpvOpDecorate:
|
||||
case spv::Op::OpDecorate:
|
||||
// We treat an OpImageTexelPointer as a load. The result type should
|
||||
// always have the Image storage class, and should not need to be
|
||||
// updated.
|
||||
case SpvOpImageTexelPointer:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
// Replace the actual use.
|
||||
context()->ForgetUses(use);
|
||||
use->SetOperand(index, {new_ptr_inst->result_id()});
|
||||
@@ -766,13 +766,13 @@ uint32_t CopyPropagateArrays::GetMemberTypeId(
|
||||
for (uint32_t element_index : access_chain) {
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeVector:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
case spv::Op::OpTypeVector:
|
||||
id = type_inst->GetSingleWordInOperand(0);
|
||||
break;
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
id = type_inst->GetSingleWordInOperand(element_index);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -134,13 +134,13 @@ class CopyPropagateArrays : public MemPass {
|
||||
var_pointer_inst->GetSingleWordInOperand(1), GetAccessIds());
|
||||
|
||||
uint32_t member_pointer_type_id = type_mgr->FindPointerToType(
|
||||
member_type_id, static_cast<SpvStorageClass>(
|
||||
member_type_id, static_cast<spv::StorageClass>(
|
||||
var_pointer_inst->GetSingleWordInOperand(0)));
|
||||
return member_pointer_type_id;
|
||||
}
|
||||
|
||||
// Returns the storage class of the memory object.
|
||||
SpvStorageClass GetStorageClass() const {
|
||||
spv::StorageClass GetStorageClass() const {
|
||||
analysis::TypeManager* type_mgr =
|
||||
GetVariable()->context()->get_type_mgr();
|
||||
const analysis::Pointer* pointer_type =
|
||||
|
||||
2
3rdparty/spirv-tools/source/opt/dataflow.cpp
vendored
2
3rdparty/spirv-tools/source/opt/dataflow.cpp
vendored
@@ -78,7 +78,7 @@ void ForwardDataFlowAnalysis::EnqueueUsers(Instruction* inst) {
|
||||
}
|
||||
|
||||
void ForwardDataFlowAnalysis::EnqueueBlockSuccessors(Instruction* inst) {
|
||||
if (inst->opcode() != SpvOpLabel) return;
|
||||
if (inst->opcode() != spv::Op::OpLabel) return;
|
||||
context()
|
||||
.cfg()
|
||||
->block(inst->result_id())
|
||||
|
||||
@@ -29,28 +29,25 @@
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kBranchCondTrueLabIdInIdx = 1;
|
||||
const uint32_t kBranchCondFalseLabIdInIdx = 2;
|
||||
|
||||
} // anonymous namespace
|
||||
constexpr uint32_t kBranchCondTrueLabIdInIdx = 1;
|
||||
constexpr uint32_t kBranchCondFalseLabIdInIdx = 2;
|
||||
} // namespace
|
||||
|
||||
bool DeadBranchElimPass::GetConstCondition(uint32_t condId, bool* condVal) {
|
||||
bool condIsConst;
|
||||
Instruction* cInst = get_def_use_mgr()->GetDef(condId);
|
||||
switch (cInst->opcode()) {
|
||||
case SpvOpConstantNull:
|
||||
case SpvOpConstantFalse: {
|
||||
case spv::Op::OpConstantNull:
|
||||
case spv::Op::OpConstantFalse: {
|
||||
*condVal = false;
|
||||
condIsConst = true;
|
||||
} break;
|
||||
case SpvOpConstantTrue: {
|
||||
case spv::Op::OpConstantTrue: {
|
||||
*condVal = true;
|
||||
condIsConst = true;
|
||||
} break;
|
||||
case SpvOpLogicalNot: {
|
||||
case spv::Op::OpLogicalNot: {
|
||||
bool negVal;
|
||||
condIsConst =
|
||||
GetConstCondition(cInst->GetSingleWordInOperand(0), &negVal);
|
||||
@@ -65,13 +62,13 @@ bool DeadBranchElimPass::GetConstInteger(uint32_t selId, uint32_t* selVal) {
|
||||
Instruction* sInst = get_def_use_mgr()->GetDef(selId);
|
||||
uint32_t typeId = sInst->type_id();
|
||||
Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
|
||||
if (!typeInst || (typeInst->opcode() != SpvOpTypeInt)) return false;
|
||||
if (!typeInst || (typeInst->opcode() != spv::Op::OpTypeInt)) return false;
|
||||
// TODO(greg-lunarg): Support non-32 bit ints
|
||||
if (typeInst->GetSingleWordInOperand(0) != 32) return false;
|
||||
if (sInst->opcode() == SpvOpConstant) {
|
||||
if (sInst->opcode() == spv::Op::OpConstant) {
|
||||
*selVal = sInst->GetSingleWordInOperand(0);
|
||||
return true;
|
||||
} else if (sInst->opcode() == SpvOpConstantNull) {
|
||||
} else if (sInst->opcode() == spv::Op::OpConstantNull) {
|
||||
*selVal = 0;
|
||||
return true;
|
||||
}
|
||||
@@ -81,7 +78,7 @@ bool DeadBranchElimPass::GetConstInteger(uint32_t selId, uint32_t* selVal) {
|
||||
void DeadBranchElimPass::AddBranch(uint32_t labelId, BasicBlock* bp) {
|
||||
assert(get_def_use_mgr()->GetDef(labelId) != nullptr);
|
||||
std::unique_ptr<Instruction> newBranch(
|
||||
new Instruction(context(), SpvOpBranch, 0, 0,
|
||||
new Instruction(context(), spv::Op::OpBranch, 0, 0,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}}));
|
||||
context()->AnalyzeDefUse(&*newBranch);
|
||||
context()->set_instr_block(&*newBranch, bp);
|
||||
@@ -115,13 +112,13 @@ bool DeadBranchElimPass::MarkLiveBlocks(
|
||||
Instruction* terminator = block->terminator();
|
||||
uint32_t live_lab_id = 0;
|
||||
// Check if the terminator has a single valid successor.
|
||||
if (terminator->opcode() == SpvOpBranchConditional) {
|
||||
if (terminator->opcode() == spv::Op::OpBranchConditional) {
|
||||
bool condVal;
|
||||
if (GetConstCondition(terminator->GetSingleWordInOperand(0u), &condVal)) {
|
||||
live_lab_id = terminator->GetSingleWordInOperand(
|
||||
condVal ? kBranchCondTrueLabIdInIdx : kBranchCondFalseLabIdInIdx);
|
||||
}
|
||||
} else if (terminator->opcode() == SpvOpSwitch) {
|
||||
} else if (terminator->opcode() == spv::Op::OpSwitch) {
|
||||
uint32_t sel_val;
|
||||
if (GetConstInteger(terminator->GetSingleWordInOperand(0u), &sel_val)) {
|
||||
// Search switch operands for selector value, set live_lab_id to
|
||||
@@ -194,8 +191,8 @@ bool DeadBranchElimPass::SimplifyBranch(BasicBlock* block,
|
||||
uint32_t live_lab_id) {
|
||||
Instruction* merge_inst = block->GetMergeInst();
|
||||
Instruction* terminator = block->terminator();
|
||||
if (merge_inst && merge_inst->opcode() == SpvOpSelectionMerge) {
|
||||
if (merge_inst->NextNode()->opcode() == SpvOpSwitch &&
|
||||
if (merge_inst && merge_inst->opcode() == spv::Op::OpSelectionMerge) {
|
||||
if (merge_inst->NextNode()->opcode() == spv::Op::OpSwitch &&
|
||||
SwitchHasNestedBreak(block->id())) {
|
||||
if (terminator->NumInOperands() == 2) {
|
||||
// We cannot remove the branch, and it already has a single case, so no
|
||||
@@ -266,7 +263,7 @@ bool DeadBranchElimPass::FixPhiNodesInLiveBlocks(
|
||||
for (auto& block : *func) {
|
||||
if (live_blocks.count(&block)) {
|
||||
for (auto iter = block.begin(); iter != block.end();) {
|
||||
if (iter->opcode() != SpvOpPhi) {
|
||||
if (iter->opcode() != spv::Op::OpPhi) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -292,7 +289,7 @@ bool DeadBranchElimPass::FixPhiNodesInLiveBlocks(
|
||||
cont_iter->second == &block && inst->NumInOperands() > 4) {
|
||||
if (get_def_use_mgr()
|
||||
->GetDef(inst->GetSingleWordInOperand(i - 1))
|
||||
->opcode() == SpvOpUndef) {
|
||||
->opcode() == spv::Op::OpUndef) {
|
||||
// Already undef incoming value, no change necessary.
|
||||
operands.push_back(inst->GetInOperand(i - 1));
|
||||
operands.push_back(inst->GetInOperand(i));
|
||||
@@ -378,14 +375,14 @@ bool DeadBranchElimPass::EraseDeadBlocks(
|
||||
if (unreachable_continues.count(&*ebi)) {
|
||||
uint32_t cont_id = unreachable_continues.find(&*ebi)->second->id();
|
||||
if (ebi->begin() != ebi->tail() ||
|
||||
ebi->terminator()->opcode() != SpvOpBranch ||
|
||||
ebi->terminator()->opcode() != spv::Op::OpBranch ||
|
||||
ebi->terminator()->GetSingleWordInOperand(0u) != cont_id) {
|
||||
// Make unreachable, but leave the label.
|
||||
KillAllInsts(&*ebi, false);
|
||||
// Add unconditional branch to header.
|
||||
assert(unreachable_continues.count(&*ebi));
|
||||
ebi->AddInstruction(MakeUnique<Instruction>(
|
||||
context(), SpvOpBranch, 0, 0,
|
||||
context(), spv::Op::OpBranch, 0, 0,
|
||||
std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_id}}}));
|
||||
get_def_use_mgr()->AnalyzeInstUse(&*ebi->tail());
|
||||
context()->set_instr_block(&*ebi->tail(), &*ebi);
|
||||
@@ -394,12 +391,12 @@ bool DeadBranchElimPass::EraseDeadBlocks(
|
||||
++ebi;
|
||||
} else if (unreachable_merges.count(&*ebi)) {
|
||||
if (ebi->begin() != ebi->tail() ||
|
||||
ebi->terminator()->opcode() != SpvOpUnreachable) {
|
||||
ebi->terminator()->opcode() != spv::Op::OpUnreachable) {
|
||||
// Make unreachable, but leave the label.
|
||||
KillAllInsts(&*ebi, false);
|
||||
// Add unreachable terminator.
|
||||
ebi->AddInstruction(
|
||||
MakeUnique<Instruction>(context(), SpvOpUnreachable, 0, 0,
|
||||
MakeUnique<Instruction>(context(), spv::Op::OpUnreachable, 0, 0,
|
||||
std::initializer_list<Operand>{}));
|
||||
context()->AnalyzeUses(ebi->terminator());
|
||||
context()->set_instr_block(ebi->terminator(), &*ebi);
|
||||
@@ -465,7 +462,7 @@ void DeadBranchElimPass::FixBlockOrder() {
|
||||
};
|
||||
|
||||
// Structured order is more intuitive so use it where possible.
|
||||
if (context()->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
|
||||
if (context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
|
||||
context()->ProcessReachableCallTree(reorder_structured);
|
||||
} else {
|
||||
context()->ProcessReachableCallTree(reorder_dominators);
|
||||
@@ -477,7 +474,8 @@ Pass::Status DeadBranchElimPass::Process() {
|
||||
// support required in KillNamesAndDecorates().
|
||||
// TODO(greg-lunarg): Add support for OpGroupDecorate
|
||||
for (auto& ai : get_module()->annotations())
|
||||
if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
|
||||
if (ai.opcode() == spv::Op::OpGroupDecorate)
|
||||
return Status::SuccessWithoutChange;
|
||||
// Process all entry point functions
|
||||
ProcessFunction pfn = [this](Function* fp) {
|
||||
return EliminateDeadBranches(fp);
|
||||
@@ -501,7 +499,7 @@ Instruction* DeadBranchElimPass::FindFirstExitFromSelectionMerge(
|
||||
Instruction* branch = start_block->terminator();
|
||||
uint32_t next_block_id = 0;
|
||||
switch (branch->opcode()) {
|
||||
case SpvOpBranchConditional:
|
||||
case spv::Op::OpBranchConditional:
|
||||
next_block_id = start_block->MergeBlockIdIfAny();
|
||||
if (next_block_id == 0) {
|
||||
// If a possible target is the |loop_merge_id| or |loop_continue_id|,
|
||||
@@ -530,7 +528,7 @@ Instruction* DeadBranchElimPass::FindFirstExitFromSelectionMerge(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvOpSwitch:
|
||||
case spv::Op::OpSwitch:
|
||||
next_block_id = start_block->MergeBlockIdIfAny();
|
||||
if (next_block_id == 0) {
|
||||
// A switch with no merge instructions can have at most 5 targets:
|
||||
@@ -578,7 +576,7 @@ Instruction* DeadBranchElimPass::FindFirstExitFromSelectionMerge(
|
||||
// The fall through is case 3.
|
||||
}
|
||||
break;
|
||||
case SpvOpBranch:
|
||||
case spv::Op::OpBranch:
|
||||
// Need to check if this is the header of a loop nested in the
|
||||
// selection construct.
|
||||
next_block_id = start_block->MergeBlockIdIfAny();
|
||||
|
||||
@@ -23,32 +23,29 @@
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kTypeVectorCountInIdx = 1;
|
||||
const uint32_t kTypeMatrixCountInIdx = 1;
|
||||
const uint32_t kTypeArrayLengthIdInIdx = 1;
|
||||
const uint32_t kTypeIntWidthInIdx = 0;
|
||||
const uint32_t kConstantValueInIdx = 0;
|
||||
const uint32_t kInsertObjectIdInIdx = 0;
|
||||
const uint32_t kInsertCompositeIdInIdx = 1;
|
||||
|
||||
} // anonymous namespace
|
||||
constexpr uint32_t kTypeVectorCountInIdx = 1;
|
||||
constexpr uint32_t kTypeMatrixCountInIdx = 1;
|
||||
constexpr uint32_t kTypeArrayLengthIdInIdx = 1;
|
||||
constexpr uint32_t kTypeIntWidthInIdx = 0;
|
||||
constexpr uint32_t kConstantValueInIdx = 0;
|
||||
constexpr uint32_t kInsertObjectIdInIdx = 0;
|
||||
constexpr uint32_t kInsertCompositeIdInIdx = 1;
|
||||
} // namespace
|
||||
|
||||
uint32_t DeadInsertElimPass::NumComponents(Instruction* typeInst) {
|
||||
switch (typeInst->opcode()) {
|
||||
case SpvOpTypeVector: {
|
||||
case spv::Op::OpTypeVector: {
|
||||
return typeInst->GetSingleWordInOperand(kTypeVectorCountInIdx);
|
||||
} break;
|
||||
case SpvOpTypeMatrix: {
|
||||
case spv::Op::OpTypeMatrix: {
|
||||
return typeInst->GetSingleWordInOperand(kTypeMatrixCountInIdx);
|
||||
} break;
|
||||
case SpvOpTypeArray: {
|
||||
case spv::Op::OpTypeArray: {
|
||||
uint32_t lenId =
|
||||
typeInst->GetSingleWordInOperand(kTypeArrayLengthIdInIdx);
|
||||
Instruction* lenInst = get_def_use_mgr()->GetDef(lenId);
|
||||
if (lenInst->opcode() != SpvOpConstant) return 0;
|
||||
if (lenInst->opcode() != spv::Op::OpConstant) return 0;
|
||||
uint32_t lenTypeId = lenInst->type_id();
|
||||
Instruction* lenTypeInst = get_def_use_mgr()->GetDef(lenTypeId);
|
||||
// TODO(greg-lunarg): Support non-32-bit array length
|
||||
@@ -56,7 +53,7 @@ uint32_t DeadInsertElimPass::NumComponents(Instruction* typeInst) {
|
||||
return 0;
|
||||
return lenInst->GetSingleWordInOperand(kConstantValueInIdx);
|
||||
} break;
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
return typeInst->NumInOperands();
|
||||
} break;
|
||||
default: { return 0; } break;
|
||||
@@ -68,10 +65,10 @@ void DeadInsertElimPass::MarkInsertChain(
|
||||
uint32_t extOffset, std::unordered_set<uint32_t>* visited_phis) {
|
||||
// Not currently optimizing array inserts.
|
||||
Instruction* typeInst = get_def_use_mgr()->GetDef(insertChain->type_id());
|
||||
if (typeInst->opcode() == SpvOpTypeArray) return;
|
||||
if (typeInst->opcode() == spv::Op::OpTypeArray) return;
|
||||
// Insert chains are only composed of inserts and phis
|
||||
if (insertChain->opcode() != SpvOpCompositeInsert &&
|
||||
insertChain->opcode() != SpvOpPhi)
|
||||
if (insertChain->opcode() != spv::Op::OpCompositeInsert &&
|
||||
insertChain->opcode() != spv::Op::OpPhi)
|
||||
return;
|
||||
// If extract indices are empty, mark all subcomponents if type
|
||||
// is constant length.
|
||||
@@ -89,7 +86,7 @@ void DeadInsertElimPass::MarkInsertChain(
|
||||
}
|
||||
}
|
||||
Instruction* insInst = insertChain;
|
||||
while (insInst->opcode() == SpvOpCompositeInsert) {
|
||||
while (insInst->opcode() == spv::Op::OpCompositeInsert) {
|
||||
// If no extract indices, mark insert and inserted object (which might
|
||||
// also be an insert chain) and continue up the chain though the input
|
||||
// composite.
|
||||
@@ -139,7 +136,7 @@ void DeadInsertElimPass::MarkInsertChain(
|
||||
insInst = get_def_use_mgr()->GetDef(compId);
|
||||
}
|
||||
// If insert chain ended with phi, do recursive call on each operand
|
||||
if (insInst->opcode() != SpvOpPhi) return;
|
||||
if (insInst->opcode() != spv::Op::OpPhi) return;
|
||||
// Mark phi visited to prevent potential infinite loop. If phi is already
|
||||
// visited, return to avoid infinite loop.
|
||||
if (visited_phis->count(insInst->result_id()) != 0) return;
|
||||
@@ -179,17 +176,17 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(Function* func) {
|
||||
for (auto bi = func->begin(); bi != func->end(); ++bi) {
|
||||
for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
|
||||
// Only process Inserts and composite Phis
|
||||
SpvOp op = ii->opcode();
|
||||
spv::Op op = ii->opcode();
|
||||
Instruction* typeInst = get_def_use_mgr()->GetDef(ii->type_id());
|
||||
if (op != SpvOpCompositeInsert &&
|
||||
(op != SpvOpPhi || !spvOpcodeIsComposite(typeInst->opcode())))
|
||||
if (op != spv::Op::OpCompositeInsert &&
|
||||
(op != spv::Op::OpPhi || !spvOpcodeIsComposite(typeInst->opcode())))
|
||||
continue;
|
||||
// The marking algorithm can be expensive for large arrays and the
|
||||
// efficacy of eliminating dead inserts into arrays is questionable.
|
||||
// Skip optimizing array inserts for now. Just mark them live.
|
||||
// TODO(greg-lunarg): Eliminate dead array inserts
|
||||
if (op == SpvOpCompositeInsert) {
|
||||
if (typeInst->opcode() == SpvOpTypeArray) {
|
||||
if (op == spv::Op::OpCompositeInsert) {
|
||||
if (typeInst->opcode() == spv::Op::OpTypeArray) {
|
||||
liveInserts_.insert(ii->result_id());
|
||||
continue;
|
||||
}
|
||||
@@ -198,11 +195,11 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(Function* func) {
|
||||
get_def_use_mgr()->ForEachUser(id, [&ii, this](Instruction* user) {
|
||||
if (user->IsCommonDebugInstr()) return;
|
||||
switch (user->opcode()) {
|
||||
case SpvOpCompositeInsert:
|
||||
case SpvOpPhi:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
case spv::Op::OpPhi:
|
||||
// Use by insert or phi does not initiate marking
|
||||
break;
|
||||
case SpvOpCompositeExtract: {
|
||||
case spv::Op::OpCompositeExtract: {
|
||||
// Capture extract indices
|
||||
std::vector<uint32_t> extIndices;
|
||||
uint32_t icnt = 0;
|
||||
@@ -226,7 +223,7 @@ bool DeadInsertElimPass::EliminateDeadInsertsOnePass(Function* func) {
|
||||
std::vector<Instruction*> dead_instructions;
|
||||
for (auto bi = func->begin(); bi != func->end(); ++bi) {
|
||||
for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
|
||||
if (ii->opcode() != SpvOpCompositeInsert) continue;
|
||||
if (ii->opcode() != spv::Op::OpCompositeInsert) continue;
|
||||
const uint32_t id = ii->result_id();
|
||||
if (liveInserts_.find(id) != liveInserts_.end()) continue;
|
||||
const uint32_t replId =
|
||||
|
||||
@@ -33,7 +33,7 @@ Pass::Status DeadVariableElimination::Process() {
|
||||
|
||||
// Get the reference count for all of the global OpVariable instructions.
|
||||
for (auto& inst : context()->types_values()) {
|
||||
if (inst.opcode() != SpvOp::SpvOpVariable) {
|
||||
if (inst.opcode() != spv::Op::OpVariable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ Pass::Status DeadVariableElimination::Process() {
|
||||
// Check the linkage. If it is exported, it could be reference somewhere
|
||||
// else, so we must keep the variable around.
|
||||
get_decoration_mgr()->ForEachDecoration(
|
||||
result_id, SpvDecorationLinkageAttributes,
|
||||
result_id, uint32_t(spv::Decoration::LinkageAttributes),
|
||||
[&count](const Instruction& linkage_instruction) {
|
||||
uint32_t last_operand = linkage_instruction.NumOperands() - 1;
|
||||
if (linkage_instruction.GetSingleWordOperand(last_operand) ==
|
||||
SpvLinkageTypeExport) {
|
||||
if (spv::LinkageType(linkage_instruction.GetSingleWordOperand(
|
||||
last_operand)) == spv::LinkageType::Export) {
|
||||
count = kMustKeep;
|
||||
}
|
||||
});
|
||||
@@ -57,7 +57,8 @@ Pass::Status DeadVariableElimination::Process() {
|
||||
// at the uses and count the number of real references.
|
||||
count = 0;
|
||||
get_def_use_mgr()->ForEachUser(result_id, [&count](Instruction* user) {
|
||||
if (!IsAnnotationInst(user->opcode()) && user->opcode() != SpvOpName) {
|
||||
if (!IsAnnotationInst(user->opcode()) &&
|
||||
user->opcode() != spv::Op::OpName) {
|
||||
++count;
|
||||
}
|
||||
});
|
||||
@@ -81,7 +82,7 @@ Pass::Status DeadVariableElimination::Process() {
|
||||
|
||||
void DeadVariableElimination::DeleteVariable(uint32_t result_id) {
|
||||
Instruction* inst = get_def_use_mgr()->GetDef(result_id);
|
||||
assert(inst->opcode() == SpvOpVariable &&
|
||||
assert(inst->opcode() == spv::Op::OpVariable &&
|
||||
"Should not be trying to delete anything other than an OpVariable.");
|
||||
|
||||
// Look for an initializer that references another variable. We need to know
|
||||
@@ -93,7 +94,7 @@ void DeadVariableElimination::DeleteVariable(uint32_t result_id) {
|
||||
// TODO: Handle OpSpecConstantOP which might be defined in terms of other
|
||||
// variables. Will probably require a unified dead code pass that does all
|
||||
// instruction types. (Issue 906)
|
||||
if (initializer->opcode() == SpvOpVariable) {
|
||||
if (initializer->opcode() == spv::Op::OpVariable) {
|
||||
uint32_t initializer_id = initializer->result_id();
|
||||
size_t& count = reference_count_[initializer_id];
|
||||
if (count != kMustKeep) {
|
||||
|
||||
@@ -22,32 +22,31 @@
|
||||
// Constants for OpenCL.DebugInfo.100 & NonSemantic.Shader.DebugInfo.100
|
||||
// extension instructions.
|
||||
|
||||
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;
|
||||
static const uint32_t kDebugFunctionOperandParentIndex = 9;
|
||||
static const uint32_t kDebugTypeCompositeOperandParentIndex = 9;
|
||||
static const uint32_t kDebugLexicalBlockOperandParentIndex = 7;
|
||||
static const uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
|
||||
static const uint32_t kDebugExpressOperandOperationIndex = 4;
|
||||
static const uint32_t kDebugDeclareOperandLocalVariableIndex = 4;
|
||||
static const uint32_t kDebugDeclareOperandVariableIndex = 5;
|
||||
static const uint32_t kDebugValueOperandExpressionIndex = 6;
|
||||
static const uint32_t kDebugOperationOperandOperationIndex = 4;
|
||||
static const uint32_t kOpVariableOperandStorageClassIndex = 2;
|
||||
static const uint32_t kDebugLocalVariableOperandParentIndex = 9;
|
||||
static const uint32_t kExtInstInstructionInIdx = 1;
|
||||
static const uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
|
||||
static const uint32_t kDebugLocalVariableOperandFlagsIndex = 10;
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace analysis {
|
||||
namespace {
|
||||
constexpr uint32_t kOpLineOperandLineIndex = 1;
|
||||
constexpr uint32_t kLineOperandIndexDebugFunction = 7;
|
||||
constexpr uint32_t kLineOperandIndexDebugLexicalBlock = 5;
|
||||
constexpr uint32_t kLineOperandIndexDebugLine = 5;
|
||||
constexpr uint32_t kDebugFunctionOperandFunctionIndex = 13;
|
||||
constexpr uint32_t kDebugFunctionDefinitionOperandDebugFunctionIndex = 4;
|
||||
constexpr uint32_t kDebugFunctionDefinitionOperandOpFunctionIndex = 5;
|
||||
constexpr uint32_t kDebugFunctionOperandParentIndex = 9;
|
||||
constexpr uint32_t kDebugTypeCompositeOperandParentIndex = 9;
|
||||
constexpr uint32_t kDebugLexicalBlockOperandParentIndex = 7;
|
||||
constexpr uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
|
||||
constexpr uint32_t kDebugExpressOperandOperationIndex = 4;
|
||||
constexpr uint32_t kDebugDeclareOperandLocalVariableIndex = 4;
|
||||
constexpr uint32_t kDebugDeclareOperandVariableIndex = 5;
|
||||
constexpr uint32_t kDebugValueOperandExpressionIndex = 6;
|
||||
constexpr uint32_t kDebugOperationOperandOperationIndex = 4;
|
||||
constexpr uint32_t kOpVariableOperandStorageClassIndex = 2;
|
||||
constexpr uint32_t kDebugLocalVariableOperandParentIndex = 9;
|
||||
constexpr uint32_t kExtInstInstructionInIdx = 1;
|
||||
constexpr uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
|
||||
constexpr uint32_t kDebugLocalVariableOperandFlagsIndex = 10;
|
||||
|
||||
void SetInlinedOperand(Instruction* dbg_inlined_at, uint32_t inlined_operand) {
|
||||
assert(dbg_inlined_at);
|
||||
@@ -156,7 +155,8 @@ void DebugInfoManager::RegisterDbgDeclare(uint32_t var_id,
|
||||
uint32_t AddNewConstInGlobals(IRContext* context, uint32_t const_value) {
|
||||
uint32_t id = context->TakeNextId();
|
||||
std::unique_ptr<Instruction> new_const(new Instruction(
|
||||
context, SpvOpConstant, context->get_type_mgr()->GetUIntTypeId(), id,
|
||||
context, spv::Op::OpConstant, context->get_type_mgr()->GetUIntTypeId(),
|
||||
id,
|
||||
{
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
|
||||
{const_value}},
|
||||
@@ -212,7 +212,7 @@ uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line,
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (line->opcode() == SpvOpLine) {
|
||||
if (line->opcode() == spv::Op::OpLine) {
|
||||
line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
|
||||
} else if (line->GetShader100DebugOpcode() ==
|
||||
NonSemanticShaderDebugInfo100DebugLine) {
|
||||
@@ -230,18 +230,19 @@ uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line,
|
||||
// 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 &&
|
||||
line->opcode() == SpvOpLine) {
|
||||
line->opcode() == spv::Op::OpLine) {
|
||||
if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse) ||
|
||||
!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisConstants))
|
||||
line_number = AddNewConstInGlobals(context(), line_number);
|
||||
else
|
||||
line_number = context()->get_constant_mgr()->GetUIntConst(line_number);
|
||||
line_number =
|
||||
context()->get_constant_mgr()->GetUIntConstId(line_number);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t result_id = context()->TakeNextId();
|
||||
std::unique_ptr<Instruction> inlined_at(new Instruction(
|
||||
context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
result_id,
|
||||
{
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {setId}},
|
||||
@@ -334,8 +335,8 @@ Instruction* DebugInfoManager::GetDebugOperationWithDeref() {
|
||||
|
||||
if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
|
||||
deref_operation = std::unique_ptr<Instruction>(new Instruction(
|
||||
context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
result_id,
|
||||
context(), spv::Op::OpExtInst,
|
||||
context()->get_type_mgr()->GetVoidTypeId(), result_id,
|
||||
{
|
||||
{SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
|
||||
{SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
|
||||
@@ -344,11 +345,11 @@ Instruction* DebugInfoManager::GetDebugOperationWithDeref() {
|
||||
{static_cast<uint32_t>(OpenCLDebugInfo100Deref)}},
|
||||
}));
|
||||
} else {
|
||||
uint32_t deref_id = context()->get_constant_mgr()->GetUIntConst(
|
||||
uint32_t deref_id = context()->get_constant_mgr()->GetUIntConstId(
|
||||
NonSemanticShaderDebugInfo100Deref);
|
||||
|
||||
deref_operation = std::unique_ptr<Instruction>(
|
||||
new Instruction(context(), SpvOpExtInst,
|
||||
new Instruction(context(), spv::Op::OpExtInst,
|
||||
context()->get_type_mgr()->GetVoidTypeId(), result_id,
|
||||
{
|
||||
{SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
|
||||
@@ -390,7 +391,7 @@ Instruction* DebugInfoManager::GetDebugInfoNone() {
|
||||
|
||||
uint32_t result_id = context()->TakeNextId();
|
||||
std::unique_ptr<Instruction> dbg_info_none_inst(new Instruction(
|
||||
context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
result_id,
|
||||
{
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
|
||||
@@ -414,7 +415,7 @@ Instruction* DebugInfoManager::GetEmptyDebugExpression() {
|
||||
|
||||
uint32_t result_id = context()->TakeNextId();
|
||||
std::unique_ptr<Instruction> empty_debug_expr(new Instruction(
|
||||
context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
result_id,
|
||||
{
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
|
||||
@@ -527,7 +528,7 @@ bool DebugInfoManager::IsDeclareVisibleToInstr(Instruction* dbg_declare,
|
||||
assert(scope != nullptr);
|
||||
|
||||
std::vector<uint32_t> scope_ids;
|
||||
if (scope->opcode() == SpvOpPhi) {
|
||||
if (scope->opcode() == spv::Op::OpPhi) {
|
||||
scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
|
||||
for (uint32_t i = 0; i < scope->NumInOperands(); i += 2) {
|
||||
auto* value = context()->get_def_use_mgr()->GetDef(
|
||||
@@ -571,8 +572,8 @@ bool DebugInfoManager::AddDebugValueForVariable(Instruction* scope_and_line,
|
||||
// Avoid inserting the new DebugValue between OpPhi or OpVariable
|
||||
// instructions.
|
||||
Instruction* insert_before = insert_pos->NextNode();
|
||||
while (insert_before->opcode() == SpvOpPhi ||
|
||||
insert_before->opcode() == SpvOpVariable) {
|
||||
while (insert_before->opcode() == spv::Op::OpPhi ||
|
||||
insert_before->opcode() == spv::Op::OpVariable) {
|
||||
insert_before = insert_before->NextNode();
|
||||
}
|
||||
modified |= AddDebugValueForDecl(dbg_decl_or_val, value_id, insert_before,
|
||||
@@ -653,9 +654,10 @@ uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare(
|
||||
}
|
||||
|
||||
auto* var = context()->get_def_use_mgr()->GetDef(var_id);
|
||||
if (var->opcode() == SpvOpVariable &&
|
||||
SpvStorageClass(var->GetSingleWordOperand(
|
||||
kOpVariableOperandStorageClassIndex)) == SpvStorageClassFunction) {
|
||||
if (var->opcode() == spv::Op::OpVariable &&
|
||||
spv::StorageClass(
|
||||
var->GetSingleWordOperand(kOpVariableOperandStorageClassIndex)) ==
|
||||
spv::StorageClass::Function) {
|
||||
return var_id;
|
||||
}
|
||||
return 0;
|
||||
@@ -762,8 +764,8 @@ void DebugInfoManager::ConvertDebugGlobalToLocalVariable(
|
||||
CommonDebugInfoDebugGlobalVariable) {
|
||||
return;
|
||||
}
|
||||
assert(local_var->opcode() == SpvOpVariable ||
|
||||
local_var->opcode() == SpvOpFunctionParameter);
|
||||
assert(local_var->opcode() == spv::Op::OpVariable ||
|
||||
local_var->opcode() == spv::Op::OpFunctionParameter);
|
||||
|
||||
// Convert |dbg_global_var| to DebugLocalVariable
|
||||
dbg_global_var->SetInOperand(kExtInstInstructionInIdx,
|
||||
@@ -780,7 +782,7 @@ void DebugInfoManager::ConvertDebugGlobalToLocalVariable(
|
||||
|
||||
// Create a DebugDeclare
|
||||
std::unique_ptr<Instruction> new_dbg_decl(new Instruction(
|
||||
context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
|
||||
context()->TakeNextId(),
|
||||
{
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
|
||||
@@ -794,7 +796,7 @@ void DebugInfoManager::ConvertDebugGlobalToLocalVariable(
|
||||
}));
|
||||
// Must insert after all OpVariables in block
|
||||
Instruction* insert_before = local_var;
|
||||
while (insert_before->opcode() == SpvOpVariable)
|
||||
while (insert_before->opcode() == spv::Op::OpVariable)
|
||||
insert_before = insert_before->NextNode();
|
||||
auto* added_dbg_decl = insert_before->InsertBefore(std::move(new_dbg_decl));
|
||||
if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace analysis {
|
||||
namespace {
|
||||
using InstructionVector = std::vector<const spvtools::opt::Instruction*>;
|
||||
using DecorationSet = std::set<std::u32string>;
|
||||
@@ -49,10 +52,6 @@ bool IsSubset(const DecorationSet& a, const DecorationSet& b) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace analysis {
|
||||
|
||||
bool DecorationManager::RemoveDecorationsFrom(
|
||||
uint32_t id, std::function<bool(const Instruction&)> pred) {
|
||||
bool was_modified = false;
|
||||
@@ -76,8 +75,8 @@ bool DecorationManager::RemoveDecorationsFrom(
|
||||
// applying the group.
|
||||
std::unordered_set<const Instruction*> indirect_decorations_to_remove;
|
||||
for (Instruction* inst : decorations_info.indirect_decorations) {
|
||||
assert(inst->opcode() == SpvOpGroupDecorate ||
|
||||
inst->opcode() == SpvOpGroupMemberDecorate);
|
||||
assert(inst->opcode() == spv::Op::OpGroupDecorate ||
|
||||
inst->opcode() == spv::Op::OpGroupMemberDecorate);
|
||||
|
||||
std::vector<Instruction*> group_decorations_to_keep;
|
||||
const uint32_t group_id = inst->GetSingleWordInOperand(0u);
|
||||
@@ -99,7 +98,8 @@ bool DecorationManager::RemoveDecorationsFrom(
|
||||
}
|
||||
|
||||
// Otherwise, remove |id| from the targets of |group_id|
|
||||
const uint32_t stride = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
|
||||
const uint32_t stride =
|
||||
inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
|
||||
for (uint32_t i = 1u; i < inst->NumInOperands();) {
|
||||
if (inst->GetSingleWordInOperand(i) != id) {
|
||||
i += stride;
|
||||
@@ -212,16 +212,16 @@ bool DecorationManager::HaveTheSameDecorations(uint32_t id1,
|
||||
}
|
||||
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpDecorate:
|
||||
case spv::Op::OpDecorate:
|
||||
decorate_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
case SpvOpMemberDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
member_decorate_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
case SpvOpDecorateId:
|
||||
case spv::Op::OpDecorateId:
|
||||
decorate_id_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
decorate_string_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
default:
|
||||
@@ -278,16 +278,16 @@ bool DecorationManager::HaveSubsetOfDecorations(uint32_t id1,
|
||||
}
|
||||
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpDecorate:
|
||||
case spv::Op::OpDecorate:
|
||||
decorate_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
case SpvOpMemberDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
member_decorate_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
case SpvOpDecorateId:
|
||||
case spv::Op::OpDecorateId:
|
||||
decorate_id_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
decorate_string_set->emplace(std::move(decoration_payload));
|
||||
break;
|
||||
default:
|
||||
@@ -328,10 +328,10 @@ bool DecorationManager::AreDecorationsTheSame(const Instruction* inst1,
|
||||
const Instruction* inst2,
|
||||
bool ignore_target) const {
|
||||
switch (inst1->opcode()) {
|
||||
case SpvOpDecorate:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case spv::Op::OpDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
case spv::Op::OpDecorateId:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
@@ -358,17 +358,18 @@ void DecorationManager::AnalyzeDecorations() {
|
||||
|
||||
void DecorationManager::AddDecoration(Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case SpvOpMemberDecorate: {
|
||||
case spv::Op::OpDecorate:
|
||||
case spv::Op::OpDecorateId:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
case spv::Op::OpMemberDecorate: {
|
||||
const auto target_id = inst->GetSingleWordInOperand(0u);
|
||||
id_to_decoration_insts_[target_id].direct_decorations.push_back(inst);
|
||||
break;
|
||||
}
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate: {
|
||||
const uint32_t start = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
|
||||
case spv::Op::OpGroupDecorate:
|
||||
case spv::Op::OpGroupMemberDecorate: {
|
||||
const uint32_t start =
|
||||
inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
|
||||
const uint32_t stride = start;
|
||||
for (uint32_t i = start; i < inst->NumInOperands(); i += stride) {
|
||||
const auto target_id = inst->GetSingleWordInOperand(i);
|
||||
@@ -384,7 +385,7 @@ void DecorationManager::AddDecoration(Instruction* inst) {
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationManager::AddDecoration(SpvOp opcode,
|
||||
void DecorationManager::AddDecoration(spv::Op opcode,
|
||||
std::vector<Operand> opnds) {
|
||||
IRContext* ctx = module_->context();
|
||||
std::unique_ptr<Instruction> newDecoOp(
|
||||
@@ -394,7 +395,7 @@ void DecorationManager::AddDecoration(SpvOp opcode,
|
||||
|
||||
void DecorationManager::AddDecoration(uint32_t inst_id, uint32_t decoration) {
|
||||
AddDecoration(
|
||||
SpvOpDecorate,
|
||||
spv::Op::OpDecorate,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}}});
|
||||
}
|
||||
@@ -402,7 +403,7 @@ void DecorationManager::AddDecoration(uint32_t inst_id, uint32_t decoration) {
|
||||
void DecorationManager::AddDecorationVal(uint32_t inst_id, uint32_t decoration,
|
||||
uint32_t decoration_value) {
|
||||
AddDecoration(
|
||||
SpvOpDecorate,
|
||||
spv::Op::OpDecorate,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
@@ -413,7 +414,7 @@ void DecorationManager::AddMemberDecoration(uint32_t inst_id, uint32_t member,
|
||||
uint32_t decoration,
|
||||
uint32_t decoration_value) {
|
||||
AddDecoration(
|
||||
SpvOpMemberDecorate,
|
||||
spv::Op::OpMemberDecorate,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {member}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}},
|
||||
@@ -436,9 +437,10 @@ std::vector<T> DecorationManager::InternalGetDecorationsFor(
|
||||
[include_linkage,
|
||||
&decorations](const std::vector<Instruction*>& direct_decorations) {
|
||||
for (Instruction* inst : direct_decorations) {
|
||||
const bool is_linkage = inst->opcode() == SpvOpDecorate &&
|
||||
inst->GetSingleWordInOperand(1u) ==
|
||||
SpvDecorationLinkageAttributes;
|
||||
const bool is_linkage =
|
||||
inst->opcode() == spv::Op::OpDecorate &&
|
||||
spv::Decoration(inst->GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::LinkageAttributes;
|
||||
if (include_linkage || !is_linkage) decorations.push_back(inst);
|
||||
}
|
||||
};
|
||||
@@ -462,14 +464,14 @@ bool DecorationManager::WhileEachDecoration(
|
||||
std::function<bool(const Instruction&)> f) {
|
||||
for (const Instruction* inst : GetDecorationsFor(id, true)) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpMemberDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
if (inst->GetSingleWordInOperand(2) == decoration) {
|
||||
if (!f(*inst)) return false;
|
||||
}
|
||||
break;
|
||||
case SpvOpDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case spv::Op::OpDecorate:
|
||||
case spv::Op::OpDecorateId:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
if (inst->GetSingleWordInOperand(1) == decoration) {
|
||||
if (!f(*inst)) return false;
|
||||
}
|
||||
@@ -523,14 +525,14 @@ void DecorationManager::CloneDecorations(uint32_t from, uint32_t to) {
|
||||
decoration_list->second.indirect_decorations;
|
||||
for (Instruction* inst : indirect_decorations) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpGroupDecorate:
|
||||
case spv::Op::OpGroupDecorate:
|
||||
context->ForgetUses(inst);
|
||||
// add |to| to list of decorated id's
|
||||
inst->AddOperand(
|
||||
Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {to}));
|
||||
context->AnalyzeUses(inst);
|
||||
break;
|
||||
case SpvOpGroupMemberDecorate: {
|
||||
case spv::Op::OpGroupMemberDecorate: {
|
||||
context->ForgetUses(inst);
|
||||
// for each (id == from), add (to, literal) as operands
|
||||
const uint32_t num_operands = inst->NumOperands();
|
||||
@@ -554,13 +556,13 @@ void DecorationManager::CloneDecorations(uint32_t from, uint32_t to) {
|
||||
|
||||
void DecorationManager::CloneDecorations(
|
||||
uint32_t from, uint32_t to,
|
||||
const std::vector<SpvDecoration>& decorations_to_copy) {
|
||||
const std::vector<spv::Decoration>& decorations_to_copy) {
|
||||
const auto decoration_list = id_to_decoration_insts_.find(from);
|
||||
if (decoration_list == id_to_decoration_insts_.end()) return;
|
||||
auto context = module_->context();
|
||||
for (Instruction* inst : decoration_list->second.direct_decorations) {
|
||||
if (std::find(decorations_to_copy.begin(), decorations_to_copy.end(),
|
||||
inst->GetSingleWordInOperand(1)) ==
|
||||
spv::Decoration(inst->GetSingleWordInOperand(1))) ==
|
||||
decorations_to_copy.end()) {
|
||||
continue;
|
||||
}
|
||||
@@ -579,11 +581,11 @@ void DecorationManager::CloneDecorations(
|
||||
decoration_list->second.indirect_decorations;
|
||||
for (Instruction* inst : indirect_decorations) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpGroupDecorate:
|
||||
case spv::Op::OpGroupDecorate:
|
||||
CloneDecorations(inst->GetSingleWordInOperand(0), to,
|
||||
decorations_to_copy);
|
||||
break;
|
||||
case SpvOpGroupMemberDecorate: {
|
||||
case spv::Op::OpGroupMemberDecorate: {
|
||||
assert(false && "The source id is not suppose to be a type.");
|
||||
break;
|
||||
}
|
||||
@@ -599,18 +601,19 @@ void DecorationManager::RemoveDecoration(Instruction* inst) {
|
||||
};
|
||||
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case SpvOpMemberDecorate: {
|
||||
case spv::Op::OpDecorate:
|
||||
case spv::Op::OpDecorateId:
|
||||
case spv::Op::OpDecorateStringGOOGLE:
|
||||
case spv::Op::OpMemberDecorate: {
|
||||
const auto target_id = inst->GetSingleWordInOperand(0u);
|
||||
auto const iter = id_to_decoration_insts_.find(target_id);
|
||||
if (iter == id_to_decoration_insts_.end()) return;
|
||||
remove_from_container(iter->second.direct_decorations);
|
||||
} break;
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate: {
|
||||
const uint32_t stride = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
|
||||
case spv::Op::OpGroupDecorate:
|
||||
case spv::Op::OpGroupMemberDecorate: {
|
||||
const uint32_t stride =
|
||||
inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
|
||||
for (uint32_t i = 1u; i < inst->NumInOperands(); i += stride) {
|
||||
const auto target_id = inst->GetSingleWordInOperand(i);
|
||||
auto const iter = id_to_decoration_insts_.find(target_id);
|
||||
|
||||
@@ -71,14 +71,14 @@ class DecorationManager {
|
||||
bool include_linkage);
|
||||
std::vector<const Instruction*> GetDecorationsFor(uint32_t id,
|
||||
bool include_linkage) const;
|
||||
// Returns whether two IDs have the same decorations. Two SpvOpGroupDecorate
|
||||
// instructions that apply the same decorations but to different IDs, still
|
||||
// count as being the same.
|
||||
// Returns whether two IDs have the same decorations. Two
|
||||
// spv::Op::OpGroupDecorate instructions that apply the same decorations but
|
||||
// to different IDs, still count as being the same.
|
||||
bool HaveTheSameDecorations(uint32_t id1, uint32_t id2) const;
|
||||
|
||||
// Returns whether two IDs have the same decorations. Two SpvOpGroupDecorate
|
||||
// instructions that apply the same decorations but to different IDs, still
|
||||
// count as being the same.
|
||||
// Returns whether two IDs have the same decorations. Two
|
||||
// spv::Op::OpGroupDecorate instructions that apply the same decorations but
|
||||
// to different IDs, still count as being the same.
|
||||
bool HaveSubsetOfDecorations(uint32_t id1, uint32_t id2) const;
|
||||
|
||||
// Returns whether the two decorations instructions are the same and are
|
||||
@@ -123,14 +123,15 @@ class DecorationManager {
|
||||
// Same as above, but only clone the decoration if the decoration operand is
|
||||
// in |decorations_to_copy|. This function has the extra restriction that
|
||||
// |from| and |to| must not be an object, not a type.
|
||||
void CloneDecorations(uint32_t from, uint32_t to,
|
||||
const std::vector<SpvDecoration>& decorations_to_copy);
|
||||
void CloneDecorations(
|
||||
uint32_t from, uint32_t to,
|
||||
const std::vector<spv::Decoration>& decorations_to_copy);
|
||||
|
||||
// Informs the decoration manager of a new decoration that it needs to track.
|
||||
void AddDecoration(Instruction* inst);
|
||||
|
||||
// Add decoration with |opcode| and operands |opnds|.
|
||||
void AddDecoration(SpvOp opcode, const std::vector<Operand> opnds);
|
||||
void AddDecoration(spv::Op opcode, const std::vector<Operand> opnds);
|
||||
|
||||
// Add |decoration| of |inst_id| to module.
|
||||
void AddDecoration(uint32_t inst_id, uint32_t decoration);
|
||||
@@ -195,9 +196,9 @@ class DecorationManager {
|
||||
|
||||
// Mapping from ids to the instructions applying a decoration to those ids.
|
||||
// In other words, for each id you get all decoration instructions
|
||||
// referencing that id, be it directly (SpvOpDecorate, SpvOpMemberDecorate
|
||||
// and SpvOpDecorateId), or indirectly (SpvOpGroupDecorate,
|
||||
// SpvOpMemberGroupDecorate).
|
||||
// referencing that id, be it directly (spv::Op::OpDecorate,
|
||||
// spv::Op::OpMemberDecorate and spv::Op::OpDecorateId), or indirectly
|
||||
// (spv::Op::OpGroupDecorate, spv::Op::OpMemberGroupDecorate).
|
||||
std::unordered_map<uint32_t, TargetData> id_to_decoration_insts_;
|
||||
// The enclosing module.
|
||||
Module* module_;
|
||||
|
||||
49
3rdparty/spirv-tools/source/opt/desc_sroa.cpp
vendored
49
3rdparty/spirv-tools/source/opt/desc_sroa.cpp
vendored
@@ -22,8 +22,9 @@ namespace opt {
|
||||
namespace {
|
||||
|
||||
bool IsDecorationBinding(Instruction* inst) {
|
||||
if (inst->opcode() != SpvOpDecorate) return false;
|
||||
return inst->GetSingleWordInOperand(1u) == SpvDecorationBinding;
|
||||
if (inst->opcode() != spv::Op::OpDecorate) return false;
|
||||
return spv::Decoration(inst->GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::Binding;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -56,7 +57,7 @@ bool DescriptorScalarReplacement::ReplaceCandidate(Instruction* var) {
|
||||
bool failed = !get_def_use_mgr()->WhileEachUser(
|
||||
var->result_id(),
|
||||
[this, &access_chain_work_list, &load_work_list](Instruction* use) {
|
||||
if (use->opcode() == SpvOpName) {
|
||||
if (use->opcode() == spv::Op::OpName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -65,11 +66,11 @@ bool DescriptorScalarReplacement::ReplaceCandidate(Instruction* var) {
|
||||
}
|
||||
|
||||
switch (use->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
access_chain_work_list.push_back(use);
|
||||
return true;
|
||||
case SpvOpLoad:
|
||||
case spv::Op::OpLoad:
|
||||
load_work_list.push_back(use);
|
||||
return true;
|
||||
default:
|
||||
@@ -184,7 +185,7 @@ void DescriptorScalarReplacement::CopyDecorationsForNewVariable(
|
||||
// Handle OpMemberDecorate instructions.
|
||||
for (auto old_decoration : get_decoration_mgr()->GetDecorationsFor(
|
||||
old_var_type->result_id(), true)) {
|
||||
assert(old_decoration->opcode() == SpvOpMemberDecorate);
|
||||
assert(old_decoration->opcode() == spv::Op::OpMemberDecorate);
|
||||
if (old_decoration->GetSingleWordInOperand(1u) != index) continue;
|
||||
CreateNewDecorationForMemberDecorate(old_decoration, new_var_id);
|
||||
}
|
||||
@@ -212,8 +213,8 @@ uint32_t DescriptorScalarReplacement::GetNewBindingForElement(
|
||||
|
||||
void DescriptorScalarReplacement::CreateNewDecorationForNewVariable(
|
||||
Instruction* old_decoration, uint32_t new_var_id, uint32_t new_binding) {
|
||||
assert(old_decoration->opcode() == SpvOpDecorate ||
|
||||
old_decoration->opcode() == SpvOpDecorateString);
|
||||
assert(old_decoration->opcode() == spv::Op::OpDecorate ||
|
||||
old_decoration->opcode() == spv::Op::OpDecorateString);
|
||||
std::unique_ptr<Instruction> new_decoration(old_decoration->Clone(context()));
|
||||
new_decoration->SetInOperand(0, {new_var_id});
|
||||
|
||||
@@ -231,25 +232,25 @@ void DescriptorScalarReplacement::CreateNewDecorationForMemberDecorate(
|
||||
auto new_decorate_operand_end = old_member_decoration->end();
|
||||
operands.insert(operands.end(), new_decorate_operand_begin,
|
||||
new_decorate_operand_end);
|
||||
get_decoration_mgr()->AddDecoration(SpvOpDecorate, std::move(operands));
|
||||
get_decoration_mgr()->AddDecoration(spv::Op::OpDecorate, std::move(operands));
|
||||
}
|
||||
|
||||
uint32_t DescriptorScalarReplacement::CreateReplacementVariable(
|
||||
Instruction* var, uint32_t idx) {
|
||||
// The storage class for the new variable is the same as the original.
|
||||
SpvStorageClass storage_class =
|
||||
static_cast<SpvStorageClass>(var->GetSingleWordInOperand(0));
|
||||
spv::StorageClass storage_class =
|
||||
static_cast<spv::StorageClass>(var->GetSingleWordInOperand(0));
|
||||
|
||||
// The type for the new variable will be a pointer to type of the elements of
|
||||
// the array.
|
||||
uint32_t ptr_type_id = var->type_id();
|
||||
Instruction* ptr_type_inst = get_def_use_mgr()->GetDef(ptr_type_id);
|
||||
assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
|
||||
assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
|
||||
"Variable should be a pointer to an array or structure.");
|
||||
uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1);
|
||||
Instruction* pointee_type_inst = get_def_use_mgr()->GetDef(pointee_type_id);
|
||||
const bool is_array = pointee_type_inst->opcode() == SpvOpTypeArray;
|
||||
const bool is_struct = pointee_type_inst->opcode() == SpvOpTypeStruct;
|
||||
const bool is_array = pointee_type_inst->opcode() == spv::Op::OpTypeArray;
|
||||
const bool is_struct = pointee_type_inst->opcode() == spv::Op::OpTypeStruct;
|
||||
assert((is_array || is_struct) &&
|
||||
"Variable should be a pointer to an array or structure.");
|
||||
|
||||
@@ -263,7 +264,7 @@ uint32_t DescriptorScalarReplacement::CreateReplacementVariable(
|
||||
// Create the variable.
|
||||
uint32_t id = TakeNextId();
|
||||
std::unique_ptr<Instruction> variable(
|
||||
new Instruction(context(), SpvOpVariable, ptr_element_type_id, id,
|
||||
new Instruction(context(), spv::Op::OpVariable, ptr_element_type_id, id,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
{static_cast<uint32_t>(storage_class)}}}));
|
||||
@@ -293,7 +294,7 @@ uint32_t DescriptorScalarReplacement::CreateReplacementVariable(
|
||||
}
|
||||
|
||||
std::unique_ptr<Instruction> new_name(new Instruction(
|
||||
context(), SpvOpName, 0, 0,
|
||||
context(), spv::Op::OpName, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {id}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
|
||||
@@ -315,14 +316,14 @@ uint32_t DescriptorScalarReplacement::GetNumBindingsUsedByType(
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
|
||||
// If it's a pointer, look at the underlying type.
|
||||
if (type_inst->opcode() == SpvOpTypePointer) {
|
||||
if (type_inst->opcode() == spv::Op::OpTypePointer) {
|
||||
type_id = type_inst->GetSingleWordInOperand(1);
|
||||
type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
}
|
||||
|
||||
// Arrays consume N*M binding numbers where N is the array length, and M is
|
||||
// the number of bindings used by each array element.
|
||||
if (type_inst->opcode() == SpvOpTypeArray) {
|
||||
if (type_inst->opcode() == spv::Op::OpTypeArray) {
|
||||
uint32_t element_type_id = type_inst->GetSingleWordInOperand(0);
|
||||
uint32_t length_id = type_inst->GetSingleWordInOperand(1);
|
||||
const analysis::Constant* length_const =
|
||||
@@ -335,7 +336,7 @@ uint32_t DescriptorScalarReplacement::GetNumBindingsUsedByType(
|
||||
|
||||
// The number of bindings consumed by a structure is the sum of the bindings
|
||||
// used by its members.
|
||||
if (type_inst->opcode() == SpvOpTypeStruct &&
|
||||
if (type_inst->opcode() == spv::Op::OpTypeStruct &&
|
||||
!descsroautil::IsTypeOfStructuredBuffer(context(), type_inst)) {
|
||||
uint32_t sum = 0;
|
||||
for (uint32_t i = 0; i < type_inst->NumInOperands(); i++)
|
||||
@@ -353,12 +354,12 @@ bool DescriptorScalarReplacement::ReplaceLoadedValue(Instruction* var,
|
||||
// |value| is the OpLoad instruction that has loaded |var|.
|
||||
// The function expects all users of |value| to be OpCompositeExtract
|
||||
// instructions. Otherwise the function returns false with an error message.
|
||||
assert(value->opcode() == SpvOpLoad);
|
||||
assert(value->opcode() == spv::Op::OpLoad);
|
||||
assert(value->GetSingleWordInOperand(0) == var->result_id());
|
||||
std::vector<Instruction*> work_list;
|
||||
bool failed = !get_def_use_mgr()->WhileEachUser(
|
||||
value->result_id(), [this, &work_list](Instruction* use) {
|
||||
if (use->opcode() != SpvOpCompositeExtract) {
|
||||
if (use->opcode() != spv::Op::OpCompositeExtract) {
|
||||
context()->EmitErrorMessage(
|
||||
"Variable cannot be replaced: invalid instruction", use);
|
||||
return false;
|
||||
@@ -384,7 +385,7 @@ bool DescriptorScalarReplacement::ReplaceLoadedValue(Instruction* var,
|
||||
|
||||
bool DescriptorScalarReplacement::ReplaceCompositeExtract(
|
||||
Instruction* var, Instruction* extract) {
|
||||
assert(extract->opcode() == SpvOpCompositeExtract);
|
||||
assert(extract->opcode() == spv::Op::OpCompositeExtract);
|
||||
// We're currently only supporting extractions of one index at a time. If we
|
||||
// need to, we can handle cases with multiple indexes in the future.
|
||||
if (extract->NumInOperands() != 2) {
|
||||
@@ -400,7 +401,7 @@ bool DescriptorScalarReplacement::ReplaceCompositeExtract(
|
||||
// OpCompositeExtract.
|
||||
uint32_t load_id = TakeNextId();
|
||||
std::unique_ptr<Instruction> load(
|
||||
new Instruction(context(), SpvOpLoad, extract->type_id(), load_id,
|
||||
new Instruction(context(), spv::Op::OpLoad, extract->type_id(), load_id,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {replacement_var}}}));
|
||||
Instruction* load_instr = load.get();
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
|
||||
const uint32_t kOpAccessChainInOperandIndexes = 1;
|
||||
constexpr uint32_t kOpAccessChainInOperandIndexes = 1;
|
||||
|
||||
// Returns the length of array type |type|.
|
||||
uint32_t GetLengthOfArrayType(IRContext* context, Instruction* type) {
|
||||
assert(type->opcode() == SpvOpTypeArray && "type must be array");
|
||||
assert(type->opcode() == spv::Op::OpTypeArray && "type must be array");
|
||||
uint32_t length_id = type->GetSingleWordInOperand(1);
|
||||
const analysis::Constant* length_const =
|
||||
context->get_constant_mgr()->FindDeclaredConstant(length_id);
|
||||
@@ -35,20 +34,20 @@ uint32_t GetLengthOfArrayType(IRContext* context, Instruction* type) {
|
||||
namespace descsroautil {
|
||||
|
||||
bool IsDescriptorArray(IRContext* context, Instruction* var) {
|
||||
if (var->opcode() != SpvOpVariable) {
|
||||
if (var->opcode() != spv::Op::OpVariable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t ptr_type_id = var->type_id();
|
||||
Instruction* ptr_type_inst = context->get_def_use_mgr()->GetDef(ptr_type_id);
|
||||
if (ptr_type_inst->opcode() != SpvOpTypePointer) {
|
||||
if (ptr_type_inst->opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t var_type_id = ptr_type_inst->GetSingleWordInOperand(1);
|
||||
Instruction* var_type_inst = context->get_def_use_mgr()->GetDef(var_type_id);
|
||||
if (var_type_inst->opcode() != SpvOpTypeArray &&
|
||||
var_type_inst->opcode() != SpvOpTypeStruct) {
|
||||
if (var_type_inst->opcode() != spv::Op::OpTypeArray &&
|
||||
var_type_inst->opcode() != spv::Op::OpTypeStruct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -59,23 +58,23 @@ bool IsDescriptorArray(IRContext* context, Instruction* var) {
|
||||
}
|
||||
|
||||
if (!context->get_decoration_mgr()->HasDecoration(
|
||||
var->result_id(), SpvDecorationDescriptorSet)) {
|
||||
var->result_id(), uint32_t(spv::Decoration::DescriptorSet))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return context->get_decoration_mgr()->HasDecoration(var->result_id(),
|
||||
SpvDecorationBinding);
|
||||
return context->get_decoration_mgr()->HasDecoration(
|
||||
var->result_id(), uint32_t(spv::Decoration::Binding));
|
||||
}
|
||||
|
||||
bool IsTypeOfStructuredBuffer(IRContext* context, const Instruction* type) {
|
||||
if (type->opcode() != SpvOpTypeStruct) {
|
||||
if (type->opcode() != spv::Op::OpTypeStruct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All buffers have offset decorations for members of their structure types.
|
||||
// This is how we distinguish it from a structure of descriptors.
|
||||
return context->get_decoration_mgr()->HasDecoration(type->result_id(),
|
||||
SpvDecorationOffset);
|
||||
return context->get_decoration_mgr()->HasDecoration(
|
||||
type->result_id(), uint32_t(spv::Decoration::Offset));
|
||||
}
|
||||
|
||||
const analysis::Constant* GetAccessChainIndexAsConst(
|
||||
@@ -99,15 +98,15 @@ uint32_t GetNumberOfElementsForArrayOrStruct(IRContext* context,
|
||||
Instruction* var) {
|
||||
uint32_t ptr_type_id = var->type_id();
|
||||
Instruction* ptr_type_inst = context->get_def_use_mgr()->GetDef(ptr_type_id);
|
||||
assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
|
||||
assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
|
||||
"Variable should be a pointer to an array or structure.");
|
||||
uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1);
|
||||
Instruction* pointee_type_inst =
|
||||
context->get_def_use_mgr()->GetDef(pointee_type_id);
|
||||
if (pointee_type_inst->opcode() == SpvOpTypeArray) {
|
||||
if (pointee_type_inst->opcode() == spv::Op::OpTypeArray) {
|
||||
return GetLengthOfArrayType(context, pointee_type_inst);
|
||||
}
|
||||
assert(pointee_type_inst->opcode() == SpvOpTypeStruct &&
|
||||
assert(pointee_type_inst->opcode() == spv::Op::OpTypeStruct &&
|
||||
"Variable should be a pointer to an array or structure.");
|
||||
return pointee_type_inst->NumInOperands();
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ bool DominatorAnalysisBase::Dominates(Instruction* a, Instruction* b) const {
|
||||
|
||||
// We handle OpLabel instructions explicitly since they are not stored in the
|
||||
// instruction list.
|
||||
if (current->opcode() == SpvOpLabel) {
|
||||
if (current->opcode() == spv::Op::OpLabel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ namespace {
|
||||
// called on each node traversed BEFORE their children.
|
||||
template <typename BBType, typename SuccessorLambda, typename PreLambda,
|
||||
typename PostLambda>
|
||||
static void DepthFirstSearch(const BBType* bb, SuccessorLambda successors,
|
||||
PreLambda pre, PostLambda post) {
|
||||
void DepthFirstSearch(const BBType* bb, SuccessorLambda successors,
|
||||
PreLambda pre, PostLambda post) {
|
||||
auto no_terminal_blocks = [](const BBType*) { return false; };
|
||||
CFA<BBType>::DepthFirstTraversal(bb, successors, pre, post,
|
||||
no_terminal_blocks);
|
||||
@@ -73,9 +73,8 @@ static void DepthFirstSearch(const BBType* bb, SuccessorLambda successors,
|
||||
// PostLambda - Lamdba matching the signature of 'void (const BBType*)' will be
|
||||
// called on each node traversed after their children.
|
||||
template <typename BBType, typename SuccessorLambda, typename PostLambda>
|
||||
static void DepthFirstSearchPostOrder(const BBType* bb,
|
||||
SuccessorLambda successors,
|
||||
PostLambda post) {
|
||||
void DepthFirstSearchPostOrder(const BBType* bb, SuccessorLambda successors,
|
||||
PostLambda post) {
|
||||
// Ignore preorder operation.
|
||||
auto nop_preorder = [](const BBType*) {};
|
||||
DepthFirstSearch(bb, successors, nop_preorder, post);
|
||||
|
||||
@@ -40,7 +40,7 @@ Pass::Status EliminateDeadConstantPass::Process() {
|
||||
context()->get_def_use_mgr()->ForEachUse(
|
||||
const_id, [&count](Instruction* user, uint32_t index) {
|
||||
(void)index;
|
||||
SpvOp op = user->opcode();
|
||||
spv::Op op = user->opcode();
|
||||
if (!(IsAnnotationInst(op) || IsDebug1Inst(op) || IsDebug2Inst(op) ||
|
||||
IsDebug3Inst(op))) {
|
||||
++count;
|
||||
@@ -59,9 +59,9 @@ Pass::Status EliminateDeadConstantPass::Process() {
|
||||
Instruction* inst = *working_list.begin();
|
||||
// Back propagate if the instruction contains IDs in its operands.
|
||||
switch (inst->opcode()) {
|
||||
case SpvOp::SpvOpConstantComposite:
|
||||
case SpvOp::SpvOpSpecConstantComposite:
|
||||
case SpvOp::SpvOpSpecConstantOp:
|
||||
case spv::Op::OpConstantComposite:
|
||||
case spv::Op::OpSpecConstantComposite:
|
||||
case spv::Op::OpSpecConstantOp:
|
||||
for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
|
||||
// SpecConstantOp instruction contains 'opcode' as its operand. Need
|
||||
// to exclude such operands when decreasing uses.
|
||||
|
||||
@@ -28,12 +28,12 @@ Module::iterator EliminateFunction(IRContext* context,
|
||||
->ForEachInst(
|
||||
[context, first_func, func_iter, &seen_func_end,
|
||||
&to_kill](Instruction* inst) {
|
||||
if (inst->opcode() == SpvOpFunctionEnd) {
|
||||
if (inst->opcode() == spv::Op::OpFunctionEnd) {
|
||||
seen_func_end = true;
|
||||
}
|
||||
// Move non-semantic instructions to the previous function or
|
||||
// global values if this is the first function.
|
||||
if (seen_func_end && inst->opcode() == SpvOpExtInst) {
|
||||
if (seen_func_end && inst->opcode() == spv::Op::OpExtInst) {
|
||||
assert(inst->IsNonSemanticInstruction());
|
||||
if (to_kill.find(inst) != to_kill.end()) return;
|
||||
std::unique_ptr<Instruction> clone(inst->Clone(context));
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
// Copyright (c) 2022 The Khronos Group Inc.
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/opt/eliminate_dead_input_components_pass.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/ir_builder.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/util/bit_vector.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kAccessChainBaseInIdx = 0;
|
||||
const uint32_t kAccessChainIndex0InIdx = 1;
|
||||
const uint32_t kConstantValueInIdx = 0;
|
||||
const uint32_t kVariableStorageClassInIdx = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
Pass::Status EliminateDeadInputComponentsPass::Process() {
|
||||
// Current functionality assumes shader capability
|
||||
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
|
||||
return Status::SuccessWithoutChange;
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
bool modified = false;
|
||||
std::vector<std::pair<Instruction*, unsigned>> arrays_to_change;
|
||||
for (auto& var : context()->types_values()) {
|
||||
if (var.opcode() != SpvOpVariable) {
|
||||
continue;
|
||||
}
|
||||
analysis::Type* var_type = type_mgr->GetType(var.type_id());
|
||||
analysis::Pointer* ptr_type = var_type->AsPointer();
|
||||
if (ptr_type == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (ptr_type->storage_class() != SpvStorageClassInput) {
|
||||
continue;
|
||||
}
|
||||
const analysis::Array* arr_type = ptr_type->pointee_type()->AsArray();
|
||||
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;
|
||||
}
|
||||
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<unsigned>(elt_types.size()) - 1;
|
||||
unsigned max_idx = FindMaxIndex(var, original_max);
|
||||
if (max_idx != original_max) {
|
||||
ChangeStructLength(var, max_idx + 1);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
unsigned EliminateDeadInputComponentsPass::FindMaxIndex(Instruction& var,
|
||||
unsigned original_max) {
|
||||
unsigned max = 0;
|
||||
bool seen_non_const_ac = false;
|
||||
assert(var.opcode() == SpvOpVariable && "must be variable");
|
||||
context()->get_def_use_mgr()->WhileEachUser(
|
||||
var.result_id(), [&max, &seen_non_const_ac, var, this](Instruction* use) {
|
||||
auto use_opcode = use->opcode();
|
||||
if (use_opcode == SpvOpLoad || use_opcode == SpvOpCopyMemory ||
|
||||
use_opcode == SpvOpCopyMemorySized ||
|
||||
use_opcode == SpvOpCopyObject) {
|
||||
seen_non_const_ac = true;
|
||||
return false;
|
||||
}
|
||||
if (use->opcode() != SpvOpAccessChain &&
|
||||
use->opcode() != SpvOpInBoundsAccessChain) {
|
||||
return true;
|
||||
}
|
||||
// OpAccessChain with no indices currently not optimized
|
||||
if (use->NumInOperands() == 1) {
|
||||
seen_non_const_ac = true;
|
||||
return false;
|
||||
}
|
||||
unsigned base_id = use->GetSingleWordInOperand(kAccessChainBaseInIdx);
|
||||
USE_ASSERT(base_id == var.result_id() && "unexpected base");
|
||||
unsigned idx_id = use->GetSingleWordInOperand(kAccessChainIndex0InIdx);
|
||||
Instruction* idx_inst = context()->get_def_use_mgr()->GetDef(idx_id);
|
||||
if (idx_inst->opcode() != SpvOpConstant) {
|
||||
seen_non_const_ac = true;
|
||||
return false;
|
||||
}
|
||||
unsigned value = idx_inst->GetSingleWordInOperand(kConstantValueInIdx);
|
||||
if (value > max) max = value;
|
||||
return true;
|
||||
});
|
||||
return seen_non_const_ac ? original_max : max;
|
||||
}
|
||||
|
||||
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_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);
|
||||
analysis::Array new_arr_ty(arr_ty->element_type(),
|
||||
arr_ty->GetConstantLengthInfo(length_id, length));
|
||||
analysis::Type* reg_new_arr_ty = type_mgr->GetRegisteredType(&new_arr_ty);
|
||||
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_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_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<const analysis::Type*> 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
|
||||
} // namespace spvtools
|
||||
258
3rdparty/spirv-tools/source/opt/eliminate_dead_io_components_pass.cpp
vendored
Normal file
258
3rdparty/spirv-tools/source/opt/eliminate_dead_io_components_pass.cpp
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
// Copyright (c) 2022 The Khronos Group Inc.
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/opt/eliminate_dead_io_components_pass.h"
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/ir_builder.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/util/bit_vector.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
constexpr uint32_t kAccessChainBaseInIdx = 0;
|
||||
constexpr uint32_t kAccessChainIndex0InIdx = 1;
|
||||
constexpr uint32_t kAccessChainIndex1InIdx = 2;
|
||||
constexpr uint32_t kConstantValueInIdx = 0;
|
||||
} // namespace
|
||||
|
||||
Pass::Status EliminateDeadIOComponentsPass::Process() {
|
||||
// Only process input and output variables
|
||||
if (elim_sclass_ != spv::StorageClass::Input &&
|
||||
elim_sclass_ != spv::StorageClass::Output) {
|
||||
if (consumer()) {
|
||||
std::string message =
|
||||
"EliminateDeadIOComponentsPass only valid for input and output "
|
||||
"variables.";
|
||||
consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
|
||||
}
|
||||
return Status::Failure;
|
||||
}
|
||||
// If safe mode, only process Input variables in vertex shader
|
||||
const auto stage = context()->GetStage();
|
||||
if (safe_mode_ && !(stage == spv::ExecutionModel::Vertex &&
|
||||
elim_sclass_ == spv::StorageClass::Input))
|
||||
return Status::SuccessWithoutChange;
|
||||
// Current functionality assumes shader capability.
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return Status::SuccessWithoutChange;
|
||||
// Current functionality assumes vert, frag, tesc, tese or geom shader.
|
||||
// TODO(issue #4988): Add GLCompute.
|
||||
if (stage != spv::ExecutionModel::Vertex &&
|
||||
stage != spv::ExecutionModel::Fragment &&
|
||||
stage != spv::ExecutionModel::TessellationControl &&
|
||||
stage != spv::ExecutionModel::TessellationEvaluation &&
|
||||
stage != spv::ExecutionModel::Geometry)
|
||||
return Status::SuccessWithoutChange;
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
bool modified = false;
|
||||
std::vector<Instruction*> vars_to_move;
|
||||
for (auto& var : context()->types_values()) {
|
||||
if (var.opcode() != spv::Op::OpVariable) {
|
||||
continue;
|
||||
}
|
||||
analysis::Type* var_type = type_mgr->GetType(var.type_id());
|
||||
analysis::Pointer* ptr_type = var_type->AsPointer();
|
||||
if (ptr_type == nullptr) {
|
||||
continue;
|
||||
}
|
||||
const auto sclass = ptr_type->storage_class();
|
||||
if (sclass != elim_sclass_) {
|
||||
continue;
|
||||
}
|
||||
// For tesc, or input variables in tese or geom shaders,
|
||||
// there is a outer per-vertex-array that must be ignored
|
||||
// for the purposes of this analysis/optimization. Do the
|
||||
// analysis on the inner type in these cases.
|
||||
bool skip_first_index = false;
|
||||
auto core_type = ptr_type->pointee_type();
|
||||
if (stage == spv::ExecutionModel::TessellationControl ||
|
||||
(sclass == spv::StorageClass::Input &&
|
||||
(stage == spv::ExecutionModel::TessellationEvaluation ||
|
||||
stage == spv::ExecutionModel::Geometry))) {
|
||||
auto arr_type = core_type->AsArray();
|
||||
if (!arr_type) continue;
|
||||
core_type = arr_type->element_type();
|
||||
skip_first_index = true;
|
||||
}
|
||||
const analysis::Array* arr_type = core_type->AsArray();
|
||||
if (arr_type != nullptr) {
|
||||
// Only process array if input of vertex shader, or output of
|
||||
// fragment shader. Otherwise, if one shader has a runtime index and the
|
||||
// other does not, interface incompatibility can occur.
|
||||
if (!((sclass == spv::StorageClass::Input &&
|
||||
stage == spv::ExecutionModel::Vertex) ||
|
||||
(sclass == spv::StorageClass::Output &&
|
||||
stage == spv::ExecutionModel::Fragment)))
|
||||
continue;
|
||||
unsigned arr_len_id = arr_type->LengthId();
|
||||
Instruction* arr_len_inst = def_use_mgr->GetDef(arr_len_id);
|
||||
if (arr_len_inst->opcode() != spv::Op::OpConstant) {
|
||||
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);
|
||||
vars_to_move.push_back(&var);
|
||||
modified = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const analysis::Struct* struct_type = core_type->AsStruct();
|
||||
if (struct_type == nullptr) continue;
|
||||
const auto elt_types = struct_type->element_types();
|
||||
unsigned original_max = static_cast<unsigned>(elt_types.size()) - 1;
|
||||
unsigned max_idx = FindMaxIndex(var, original_max, skip_first_index);
|
||||
if (max_idx != original_max) {
|
||||
ChangeIOVarStructLength(var, max_idx + 1);
|
||||
vars_to_move.push_back(&var);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Move changed vars after their new type instruction to preserve backward
|
||||
// referencing.
|
||||
for (auto var : vars_to_move) {
|
||||
auto type_id = var->type_id();
|
||||
auto type_inst = def_use_mgr->GetDef(type_id);
|
||||
var->RemoveFromList();
|
||||
var->InsertAfter(type_inst);
|
||||
}
|
||||
|
||||
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
unsigned EliminateDeadIOComponentsPass::FindMaxIndex(
|
||||
const Instruction& var, const unsigned original_max,
|
||||
const bool skip_first_index) {
|
||||
unsigned max = 0;
|
||||
bool seen_non_const_ac = false;
|
||||
assert(var.opcode() == spv::Op::OpVariable && "must be variable");
|
||||
context()->get_def_use_mgr()->WhileEachUser(
|
||||
var.result_id(), [&max, &seen_non_const_ac, var, skip_first_index,
|
||||
this](Instruction* use) {
|
||||
auto use_opcode = use->opcode();
|
||||
if (use_opcode == spv::Op::OpLoad || use_opcode == spv::Op::OpStore ||
|
||||
use_opcode == spv::Op::OpCopyMemory ||
|
||||
use_opcode == spv::Op::OpCopyMemorySized ||
|
||||
use_opcode == spv::Op::OpCopyObject) {
|
||||
seen_non_const_ac = true;
|
||||
return false;
|
||||
}
|
||||
if (use->opcode() != spv::Op::OpAccessChain &&
|
||||
use->opcode() != spv::Op::OpInBoundsAccessChain) {
|
||||
return true;
|
||||
}
|
||||
// OpAccessChain with no indices currently not optimized
|
||||
if (use->NumInOperands() == 1 ||
|
||||
(skip_first_index && use->NumInOperands() == 2)) {
|
||||
seen_non_const_ac = true;
|
||||
return false;
|
||||
}
|
||||
const unsigned base_id =
|
||||
use->GetSingleWordInOperand(kAccessChainBaseInIdx);
|
||||
USE_ASSERT(base_id == var.result_id() && "unexpected base");
|
||||
const unsigned in_idx = skip_first_index ? kAccessChainIndex1InIdx
|
||||
: kAccessChainIndex0InIdx;
|
||||
const unsigned idx_id = use->GetSingleWordInOperand(in_idx);
|
||||
Instruction* idx_inst = context()->get_def_use_mgr()->GetDef(idx_id);
|
||||
if (idx_inst->opcode() != spv::Op::OpConstant) {
|
||||
seen_non_const_ac = true;
|
||||
return false;
|
||||
}
|
||||
unsigned value = idx_inst->GetSingleWordInOperand(kConstantValueInIdx);
|
||||
if (value > max) max = value;
|
||||
return true;
|
||||
});
|
||||
return seen_non_const_ac ? original_max : max;
|
||||
}
|
||||
|
||||
void EliminateDeadIOComponentsPass::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_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->GetUIntConstId(length);
|
||||
analysis::Array new_arr_ty(arr_ty->element_type(),
|
||||
arr_ty->GetConstantLengthInfo(length_id, length));
|
||||
analysis::Type* reg_new_arr_ty = type_mgr->GetRegisteredType(&new_arr_ty);
|
||||
analysis::Pointer new_ptr_ty(reg_new_arr_ty, ptr_type->storage_class());
|
||||
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_var.SetResultType(new_ptr_ty_id);
|
||||
def_use_mgr->AnalyzeInstUse(&arr_var);
|
||||
}
|
||||
|
||||
void EliminateDeadIOComponentsPass::ChangeIOVarStructLength(Instruction& io_var,
|
||||
unsigned length) {
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
analysis::Pointer* ptr_type =
|
||||
type_mgr->GetType(io_var.type_id())->AsPointer();
|
||||
auto core_type = ptr_type->pointee_type();
|
||||
// Check for per-vertex-array of struct from tesc, tese and geom and grab
|
||||
// embedded struct type.
|
||||
const auto arr_type = core_type->AsArray();
|
||||
if (arr_type) core_type = arr_type->element_type();
|
||||
const analysis::Struct* struct_ty = core_type->AsStruct();
|
||||
assert(struct_ty && "expecting struct type");
|
||||
const auto orig_elt_types = struct_ty->element_types();
|
||||
std::vector<const analysis::Type*> 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);
|
||||
uint32_t old_struct_ty_id = type_mgr->GetTypeInstruction(struct_ty);
|
||||
std::vector<Instruction*> decorations =
|
||||
context()->get_decoration_mgr()->GetDecorationsFor(old_struct_ty_id,
|
||||
true);
|
||||
for (auto dec : decorations) {
|
||||
if (dec->opcode() == spv::Op::OpMemberDecorate) {
|
||||
uint32_t midx = dec->GetSingleWordInOperand(1);
|
||||
if (midx >= length) continue;
|
||||
}
|
||||
type_mgr->AttachDecoration(*dec, &new_struct_ty);
|
||||
}
|
||||
// Clone name instructions for new struct type
|
||||
analysis::Type* reg_new_str_ty = type_mgr->GetRegisteredType(&new_struct_ty);
|
||||
uint32_t new_struct_ty_id = type_mgr->GetTypeInstruction(reg_new_str_ty);
|
||||
context()->CloneNames(old_struct_ty_id, new_struct_ty_id, length);
|
||||
// Attach new type to var
|
||||
analysis::Type* reg_new_var_ty = reg_new_str_ty;
|
||||
if (arr_type) {
|
||||
analysis::Array new_arr_ty(reg_new_var_ty, arr_type->length_info());
|
||||
reg_new_var_ty = type_mgr->GetRegisteredType(&new_arr_ty);
|
||||
}
|
||||
analysis::Pointer new_ptr_ty(reg_new_var_ty, elim_sclass_);
|
||||
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);
|
||||
io_var.SetResultType(new_ptr_ty_id);
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
def_use_mgr->AnalyzeInstUse(&io_var);
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
@@ -26,14 +26,15 @@ namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// See optimizer.hpp for documentation.
|
||||
class EliminateDeadInputComponentsPass : public Pass {
|
||||
class EliminateDeadIOComponentsPass : public Pass {
|
||||
public:
|
||||
explicit EliminateDeadInputComponentsPass() {}
|
||||
explicit EliminateDeadIOComponentsPass(spv::StorageClass elim_sclass,
|
||||
bool safe_mode = true)
|
||||
: elim_sclass_(elim_sclass), safe_mode_(safe_mode) {}
|
||||
|
||||
const char* name() const override {
|
||||
return "eliminate-dead-input-components";
|
||||
}
|
||||
|
||||
Status Process() override;
|
||||
|
||||
// Return the mask of preserved Analyses.
|
||||
@@ -50,13 +51,22 @@ class EliminateDeadInputComponentsPass : public Pass {
|
||||
// Find the max constant used to index the variable declared by |var|
|
||||
// through OpAccessChain or OpInBoundsAccessChain. If any non-constant
|
||||
// indices or non-Op*AccessChain use of |var|, return |original_max|.
|
||||
unsigned FindMaxIndex(Instruction& var, unsigned original_max);
|
||||
unsigned FindMaxIndex(const Instruction& var, const unsigned original_max,
|
||||
const bool skip_first_index = false);
|
||||
|
||||
// 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);
|
||||
// Change the length of the struct in |io_var| to |length|. |io_var|
|
||||
// is either the struct or a per-vertex-array of the struct.
|
||||
void ChangeIOVarStructLength(Instruction& io_var, unsigned length);
|
||||
|
||||
// Storage class to be optimized. Must be Input or Output.
|
||||
spv::StorageClass elim_sclass_;
|
||||
|
||||
// Only make changes that will not cause interface incompatibility if done
|
||||
// standalone. Currently this is only Input variables in vertex shaders.
|
||||
bool safe_mode_;
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
@@ -17,17 +17,16 @@
|
||||
#include "ir_builder.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
const uint32_t kRemovedMember = 0xFFFFFFFF;
|
||||
const uint32_t kSpecConstOpOpcodeIdx = 0;
|
||||
constexpr uint32_t kRemovedMember = 0xFFFFFFFF;
|
||||
constexpr uint32_t kSpecConstOpOpcodeIdx = 0;
|
||||
constexpr uint32_t kArrayElementTypeIdx = 0;
|
||||
} // namespace
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
Pass::Status EliminateDeadMembersPass::Process() {
|
||||
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return Status::SuccessWithoutChange;
|
||||
|
||||
FindLiveMembers();
|
||||
@@ -41,27 +40,27 @@ void EliminateDeadMembersPass::FindLiveMembers() {
|
||||
// Until we have implemented the rewriting of OpSpecConsantOp instructions,
|
||||
// we have to mark them as fully used just to be safe.
|
||||
for (auto& inst : get_module()->types_values()) {
|
||||
if (inst.opcode() == SpvOpSpecConstantOp) {
|
||||
switch (inst.GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
|
||||
case SpvOpCompositeExtract:
|
||||
if (inst.opcode() == spv::Op::OpSpecConstantOp) {
|
||||
switch (spv::Op(inst.GetSingleWordInOperand(kSpecConstOpOpcodeIdx))) {
|
||||
case spv::Op::OpCompositeExtract:
|
||||
MarkMembersAsLiveForExtract(&inst);
|
||||
break;
|
||||
case SpvOpCompositeInsert:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
// Nothing specific to do.
|
||||
break;
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
assert(false && "Not implemented yet.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (inst.opcode() == SpvOpVariable) {
|
||||
switch (inst.GetSingleWordInOperand(0)) {
|
||||
case SpvStorageClassInput:
|
||||
case SpvStorageClassOutput:
|
||||
} else if (inst.opcode() == spv::Op::OpVariable) {
|
||||
switch (spv::StorageClass(inst.GetSingleWordInOperand(0))) {
|
||||
case spv::StorageClass::Input:
|
||||
case spv::StorageClass::Output:
|
||||
MarkPointeeTypeAsFullUsed(inst.type_id());
|
||||
break;
|
||||
default:
|
||||
@@ -86,34 +85,34 @@ void EliminateDeadMembersPass::FindLiveMembers(const Function& function) {
|
||||
|
||||
void EliminateDeadMembersPass::FindLiveMembers(const Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpStore:
|
||||
case spv::Op::OpStore:
|
||||
MarkMembersAsLiveForStore(inst);
|
||||
break;
|
||||
case SpvOpCopyMemory:
|
||||
case SpvOpCopyMemorySized:
|
||||
case spv::Op::OpCopyMemory:
|
||||
case spv::Op::OpCopyMemorySized:
|
||||
MarkMembersAsLiveForCopyMemory(inst);
|
||||
break;
|
||||
case SpvOpCompositeExtract:
|
||||
case spv::Op::OpCompositeExtract:
|
||||
MarkMembersAsLiveForExtract(inst);
|
||||
break;
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
MarkMembersAsLiveForAccessChain(inst);
|
||||
break;
|
||||
case SpvOpReturnValue:
|
||||
case spv::Op::OpReturnValue:
|
||||
// This should be an issue only if we are returning from the entry point.
|
||||
// However, for now I will keep it more conservative because functions are
|
||||
// often inlined leaving only the entry points.
|
||||
MarkOperandTypeAsFullyUsed(inst, 0);
|
||||
break;
|
||||
case SpvOpArrayLength:
|
||||
case spv::Op::OpArrayLength:
|
||||
MarkMembersAsLiveForArrayLength(inst);
|
||||
break;
|
||||
case SpvOpLoad:
|
||||
case SpvOpCompositeInsert:
|
||||
case SpvOpCompositeConstruct:
|
||||
case spv::Op::OpLoad:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
case spv::Op::OpCompositeConstruct:
|
||||
break;
|
||||
default:
|
||||
// This path is here for safety. All instructions that can reference
|
||||
@@ -131,7 +130,7 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForStore(
|
||||
// memory that is read outside of the shader. Other passes can remove all
|
||||
// store to memory that is not visible outside of the shader, so we do not
|
||||
// complicate the code for now.
|
||||
assert(inst->opcode() == SpvOpStore);
|
||||
assert(inst->opcode() == spv::Op::OpStore);
|
||||
uint32_t object_id = inst->GetSingleWordInOperand(1);
|
||||
Instruction* object_inst = context()->get_def_use_mgr()->GetDef(object_id);
|
||||
uint32_t object_type_id = object_inst->type_id();
|
||||
@@ -143,15 +142,15 @@ void EliminateDeadMembersPass::MarkTypeAsFullyUsed(uint32_t type_id) {
|
||||
assert(type_inst != nullptr);
|
||||
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
// Mark every member and its type as fully used.
|
||||
for (uint32_t i = 0; i < type_inst->NumInOperands(); ++i) {
|
||||
used_members_[type_id].insert(i);
|
||||
MarkTypeAsFullyUsed(type_inst->GetSingleWordInOperand(i));
|
||||
}
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
MarkTypeAsFullyUsed(
|
||||
type_inst->GetSingleWordInOperand(kArrayElementTypeIdx));
|
||||
break;
|
||||
@@ -162,7 +161,7 @@ void EliminateDeadMembersPass::MarkTypeAsFullyUsed(uint32_t type_id) {
|
||||
|
||||
void EliminateDeadMembersPass::MarkPointeeTypeAsFullUsed(uint32_t ptr_type_id) {
|
||||
Instruction* ptr_type_inst = get_def_use_mgr()->GetDef(ptr_type_id);
|
||||
assert(ptr_type_inst->opcode() == SpvOpTypePointer);
|
||||
assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer);
|
||||
MarkTypeAsFullyUsed(ptr_type_inst->GetSingleWordInOperand(1));
|
||||
}
|
||||
|
||||
@@ -178,12 +177,13 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForCopyMemory(
|
||||
|
||||
void EliminateDeadMembersPass::MarkMembersAsLiveForExtract(
|
||||
const Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpCompositeExtract ||
|
||||
(inst->opcode() == SpvOpSpecConstantOp &&
|
||||
inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
|
||||
SpvOpCompositeExtract));
|
||||
assert(inst->opcode() == spv::Op::OpCompositeExtract ||
|
||||
(inst->opcode() == spv::Op::OpSpecConstantOp &&
|
||||
spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
|
||||
spv::Op::OpCompositeExtract));
|
||||
|
||||
uint32_t first_operand = (inst->opcode() == SpvOpSpecConstantOp ? 1 : 0);
|
||||
uint32_t first_operand =
|
||||
(inst->opcode() == spv::Op::OpSpecConstantOp ? 1 : 0);
|
||||
uint32_t composite_id = inst->GetSingleWordInOperand(first_operand);
|
||||
Instruction* composite_inst = get_def_use_mgr()->GetDef(composite_id);
|
||||
uint32_t type_id = composite_inst->type_id();
|
||||
@@ -192,14 +192,14 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForExtract(
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
uint32_t member_idx = inst->GetSingleWordInOperand(i);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
used_members_[type_id].insert(member_idx);
|
||||
type_id = type_inst->GetSingleWordInOperand(member_idx);
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
type_id = type_inst->GetSingleWordInOperand(0);
|
||||
break;
|
||||
default:
|
||||
@@ -210,10 +210,10 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForExtract(
|
||||
|
||||
void EliminateDeadMembersPass::MarkMembersAsLiveForAccessChain(
|
||||
const Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsAccessChain ||
|
||||
inst->opcode() == SpvOpPtrAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsPtrAccessChain);
|
||||
assert(inst->opcode() == spv::Op::OpAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsAccessChain ||
|
||||
inst->opcode() == spv::Op::OpPtrAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsPtrAccessChain);
|
||||
|
||||
uint32_t pointer_id = inst->GetSingleWordInOperand(0);
|
||||
Instruction* pointer_inst = get_def_use_mgr()->GetDef(pointer_id);
|
||||
@@ -225,14 +225,14 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForAccessChain(
|
||||
|
||||
// For a pointer access chain, we need to skip the |element| index. It is not
|
||||
// a reference to the member of a struct, and it does not change the type.
|
||||
uint32_t i = (inst->opcode() == SpvOpAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsAccessChain
|
||||
uint32_t i = (inst->opcode() == spv::Op::OpAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsAccessChain
|
||||
? 1
|
||||
: 2);
|
||||
for (; i < inst->NumInOperands(); ++i) {
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
const analysis::IntConstant* member_idx =
|
||||
const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
|
||||
->AsIntConstant();
|
||||
@@ -242,10 +242,10 @@ void EliminateDeadMembersPass::MarkMembersAsLiveForAccessChain(
|
||||
used_members_[type_id].insert(index);
|
||||
type_id = type_inst->GetSingleWordInOperand(index);
|
||||
} break;
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
type_id = type_inst->GetSingleWordInOperand(0);
|
||||
break;
|
||||
default:
|
||||
@@ -263,7 +263,7 @@ void EliminateDeadMembersPass::MarkOperandTypeAsFullyUsed(
|
||||
|
||||
void EliminateDeadMembersPass::MarkMembersAsLiveForArrayLength(
|
||||
const Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpArrayLength);
|
||||
assert(inst->opcode() == spv::Op::OpArrayLength);
|
||||
uint32_t object_id = inst->GetSingleWordInOperand(0);
|
||||
Instruction* object_inst = get_def_use_mgr()->GetDef(object_id);
|
||||
uint32_t pointer_type_id = object_inst->type_id();
|
||||
@@ -278,7 +278,7 @@ bool EliminateDeadMembersPass::RemoveDeadMembers() {
|
||||
// First update all of the OpTypeStruct instructions.
|
||||
get_module()->ForEachInst([&modified, this](Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
modified |= UpdateOpTypeStruct(inst);
|
||||
break;
|
||||
default:
|
||||
@@ -289,47 +289,47 @@ bool EliminateDeadMembersPass::RemoveDeadMembers() {
|
||||
// Now update all of the instructions that reference the OpTypeStructs.
|
||||
get_module()->ForEachInst([&modified, this](Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpMemberName:
|
||||
case spv::Op::OpMemberName:
|
||||
modified |= UpdateOpMemberNameOrDecorate(inst);
|
||||
break;
|
||||
case SpvOpMemberDecorate:
|
||||
case spv::Op::OpMemberDecorate:
|
||||
modified |= UpdateOpMemberNameOrDecorate(inst);
|
||||
break;
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case spv::Op::OpGroupMemberDecorate:
|
||||
modified |= UpdateOpGroupMemberDecorate(inst);
|
||||
break;
|
||||
case SpvOpSpecConstantComposite:
|
||||
case SpvOpConstantComposite:
|
||||
case SpvOpCompositeConstruct:
|
||||
case spv::Op::OpSpecConstantComposite:
|
||||
case spv::Op::OpConstantComposite:
|
||||
case spv::Op::OpCompositeConstruct:
|
||||
modified |= UpdateConstantComposite(inst);
|
||||
break;
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
modified |= UpdateAccessChain(inst);
|
||||
break;
|
||||
case SpvOpCompositeExtract:
|
||||
case spv::Op::OpCompositeExtract:
|
||||
modified |= UpdateCompsiteExtract(inst);
|
||||
break;
|
||||
case SpvOpCompositeInsert:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
modified |= UpdateCompositeInsert(inst);
|
||||
break;
|
||||
case SpvOpArrayLength:
|
||||
case spv::Op::OpArrayLength:
|
||||
modified |= UpdateOpArrayLength(inst);
|
||||
break;
|
||||
case SpvOpSpecConstantOp:
|
||||
switch (inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
|
||||
case SpvOpCompositeExtract:
|
||||
case spv::Op::OpSpecConstantOp:
|
||||
switch (spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx))) {
|
||||
case spv::Op::OpCompositeExtract:
|
||||
modified |= UpdateCompsiteExtract(inst);
|
||||
break;
|
||||
case SpvOpCompositeInsert:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
modified |= UpdateCompositeInsert(inst);
|
||||
break;
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
assert(false && "Not implemented yet.");
|
||||
break;
|
||||
default:
|
||||
@@ -344,7 +344,7 @@ bool EliminateDeadMembersPass::RemoveDeadMembers() {
|
||||
}
|
||||
|
||||
bool EliminateDeadMembersPass::UpdateOpTypeStruct(Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpTypeStruct);
|
||||
assert(inst->opcode() == spv::Op::OpTypeStruct);
|
||||
|
||||
const auto& live_members = used_members_[inst->result_id()];
|
||||
if (live_members.size() == inst->NumInOperands()) {
|
||||
@@ -362,8 +362,8 @@ bool EliminateDeadMembersPass::UpdateOpTypeStruct(Instruction* inst) {
|
||||
}
|
||||
|
||||
bool EliminateDeadMembersPass::UpdateOpMemberNameOrDecorate(Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpMemberName ||
|
||||
inst->opcode() == SpvOpMemberDecorate);
|
||||
assert(inst->opcode() == spv::Op::OpMemberName ||
|
||||
inst->opcode() == spv::Op::OpMemberDecorate);
|
||||
|
||||
uint32_t type_id = inst->GetSingleWordInOperand(0);
|
||||
auto live_members = used_members_.find(type_id);
|
||||
@@ -388,7 +388,7 @@ bool EliminateDeadMembersPass::UpdateOpMemberNameOrDecorate(Instruction* inst) {
|
||||
}
|
||||
|
||||
bool EliminateDeadMembersPass::UpdateOpGroupMemberDecorate(Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpGroupMemberDecorate);
|
||||
assert(inst->opcode() == spv::Op::OpGroupMemberDecorate);
|
||||
|
||||
bool modified = false;
|
||||
|
||||
@@ -429,9 +429,9 @@ bool EliminateDeadMembersPass::UpdateOpGroupMemberDecorate(Instruction* inst) {
|
||||
}
|
||||
|
||||
bool EliminateDeadMembersPass::UpdateConstantComposite(Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpSpecConstantComposite ||
|
||||
inst->opcode() == SpvOpConstantComposite ||
|
||||
inst->opcode() == SpvOpCompositeConstruct);
|
||||
assert(inst->opcode() == spv::Op::OpSpecConstantComposite ||
|
||||
inst->opcode() == spv::Op::OpConstantComposite ||
|
||||
inst->opcode() == spv::Op::OpCompositeConstruct);
|
||||
uint32_t type_id = inst->type_id();
|
||||
|
||||
bool modified = false;
|
||||
@@ -450,10 +450,10 @@ bool EliminateDeadMembersPass::UpdateConstantComposite(Instruction* inst) {
|
||||
}
|
||||
|
||||
bool EliminateDeadMembersPass::UpdateAccessChain(Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsAccessChain ||
|
||||
inst->opcode() == SpvOpPtrAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsPtrAccessChain);
|
||||
assert(inst->opcode() == spv::Op::OpAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsAccessChain ||
|
||||
inst->opcode() == spv::Op::OpPtrAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsPtrAccessChain);
|
||||
|
||||
uint32_t pointer_id = inst->GetSingleWordInOperand(0);
|
||||
Instruction* pointer_inst = get_def_use_mgr()->GetDef(pointer_id);
|
||||
@@ -467,8 +467,8 @@ bool EliminateDeadMembersPass::UpdateAccessChain(Instruction* inst) {
|
||||
new_operands.emplace_back(inst->GetInOperand(0));
|
||||
|
||||
// For pointer access chains we want to copy the element operand.
|
||||
if (inst->opcode() == SpvOpPtrAccessChain ||
|
||||
inst->opcode() == SpvOpInBoundsPtrAccessChain) {
|
||||
if (inst->opcode() == spv::Op::OpPtrAccessChain ||
|
||||
inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) {
|
||||
new_operands.emplace_back(inst->GetInOperand(1));
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ bool EliminateDeadMembersPass::UpdateAccessChain(Instruction* inst) {
|
||||
i < inst->NumInOperands(); ++i) {
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
const analysis::IntConstant* member_idx =
|
||||
const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
|
||||
->AsIntConstant();
|
||||
@@ -501,10 +501,10 @@ bool EliminateDeadMembersPass::UpdateAccessChain(Instruction* inst) {
|
||||
// index.
|
||||
type_id = type_inst->GetSingleWordInOperand(new_member_idx);
|
||||
} break;
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
new_operands.emplace_back(inst->GetInOperand(i));
|
||||
type_id = type_inst->GetSingleWordInOperand(0);
|
||||
break;
|
||||
@@ -539,13 +539,13 @@ uint32_t EliminateDeadMembersPass::GetNewMemberIndex(uint32_t type_id,
|
||||
}
|
||||
|
||||
bool EliminateDeadMembersPass::UpdateCompsiteExtract(Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpCompositeExtract ||
|
||||
(inst->opcode() == SpvOpSpecConstantOp &&
|
||||
inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
|
||||
SpvOpCompositeExtract));
|
||||
assert(inst->opcode() == spv::Op::OpCompositeExtract ||
|
||||
(inst->opcode() == spv::Op::OpSpecConstantOp &&
|
||||
spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
|
||||
spv::Op::OpCompositeExtract));
|
||||
|
||||
uint32_t first_operand = 0;
|
||||
if (inst->opcode() == SpvOpSpecConstantOp) {
|
||||
if (inst->opcode() == spv::Op::OpSpecConstantOp) {
|
||||
first_operand = 1;
|
||||
}
|
||||
uint32_t object_id = inst->GetSingleWordInOperand(first_operand);
|
||||
@@ -569,15 +569,15 @@ bool EliminateDeadMembersPass::UpdateCompsiteExtract(Instruction* inst) {
|
||||
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
// The type will have already been rewritten, so use the new member
|
||||
// index.
|
||||
type_id = type_inst->GetSingleWordInOperand(new_member_idx);
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
type_id = type_inst->GetSingleWordInOperand(0);
|
||||
break;
|
||||
default:
|
||||
@@ -594,13 +594,13 @@ bool EliminateDeadMembersPass::UpdateCompsiteExtract(Instruction* inst) {
|
||||
}
|
||||
|
||||
bool EliminateDeadMembersPass::UpdateCompositeInsert(Instruction* inst) {
|
||||
assert(inst->opcode() == SpvOpCompositeInsert ||
|
||||
(inst->opcode() == SpvOpSpecConstantOp &&
|
||||
inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
|
||||
SpvOpCompositeInsert));
|
||||
assert(inst->opcode() == spv::Op::OpCompositeInsert ||
|
||||
(inst->opcode() == spv::Op::OpSpecConstantOp &&
|
||||
spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
|
||||
spv::Op::OpCompositeInsert));
|
||||
|
||||
uint32_t first_operand = 0;
|
||||
if (inst->opcode() == SpvOpSpecConstantOp) {
|
||||
if (inst->opcode() == spv::Op::OpSpecConstantOp) {
|
||||
first_operand = 1;
|
||||
}
|
||||
|
||||
@@ -630,15 +630,15 @@ bool EliminateDeadMembersPass::UpdateCompositeInsert(Instruction* inst) {
|
||||
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeStruct:
|
||||
case spv::Op::OpTypeStruct:
|
||||
// The type will have already been rewritten, so use the new member
|
||||
// index.
|
||||
type_id = type_inst->GetSingleWordInOperand(new_member_idx);
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeVector:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
type_id = type_inst->GetSingleWordInOperand(0);
|
||||
break;
|
||||
default:
|
||||
|
||||
237
3rdparty/spirv-tools/source/opt/eliminate_dead_output_stores_pass.cpp
vendored
Normal file
237
3rdparty/spirv-tools/source/opt/eliminate_dead_output_stores_pass.cpp
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright (c) 2022 The Khronos Group Inc.
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/opt/eliminate_dead_output_stores_pass.h"
|
||||
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
constexpr uint32_t kDecorationLocationInIdx = 2;
|
||||
constexpr uint32_t kOpDecorateMemberMemberInIdx = 1;
|
||||
constexpr uint32_t kOpDecorateBuiltInLiteralInIdx = 2;
|
||||
constexpr uint32_t kOpDecorateMemberBuiltInLiteralInIdx = 3;
|
||||
constexpr uint32_t kOpAccessChainIdx0InIdx = 1;
|
||||
constexpr uint32_t kOpConstantValueInIdx = 0;
|
||||
} // namespace
|
||||
|
||||
Pass::Status EliminateDeadOutputStoresPass::Process() {
|
||||
// Current functionality assumes shader capability
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return Status::SuccessWithoutChange;
|
||||
Pass::Status status = DoDeadOutputStoreElimination();
|
||||
return status;
|
||||
}
|
||||
|
||||
void EliminateDeadOutputStoresPass::InitializeElimination() {
|
||||
kill_list_.clear();
|
||||
}
|
||||
|
||||
bool EliminateDeadOutputStoresPass::IsLiveBuiltin(uint32_t bi) {
|
||||
return live_builtins_->find(bi) != live_builtins_->end();
|
||||
}
|
||||
|
||||
bool EliminateDeadOutputStoresPass::AnyLocsAreLive(uint32_t start,
|
||||
uint32_t count) {
|
||||
auto finish = start + count;
|
||||
for (uint32_t u = start; u < finish; ++u) {
|
||||
if (live_locs_->find(u) != live_locs_->end()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EliminateDeadOutputStoresPass::KillAllStoresOfRef(Instruction* ref) {
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
if (ref->opcode() == spv::Op::OpStore) {
|
||||
kill_list_.push_back(ref);
|
||||
return;
|
||||
}
|
||||
assert((ref->opcode() == spv::Op::OpAccessChain ||
|
||||
ref->opcode() == spv::Op::OpInBoundsAccessChain) &&
|
||||
"unexpected use of output variable");
|
||||
def_use_mgr->ForEachUser(ref, [this](Instruction* user) {
|
||||
if (user->opcode() == spv::Op::OpStore) kill_list_.push_back(user);
|
||||
});
|
||||
}
|
||||
|
||||
void EliminateDeadOutputStoresPass::KillAllDeadStoresOfLocRef(
|
||||
Instruction* ref, Instruction* var) {
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
|
||||
analysis::LivenessManager* live_mgr = context()->get_liveness_mgr();
|
||||
// Find variable location if present.
|
||||
uint32_t start_loc = 0;
|
||||
auto var_id = var->result_id();
|
||||
bool no_loc = deco_mgr->WhileEachDecoration(
|
||||
var_id, uint32_t(spv::Decoration::Location),
|
||||
[&start_loc](const Instruction& deco) {
|
||||
assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
|
||||
start_loc = deco.GetSingleWordInOperand(kDecorationLocationInIdx);
|
||||
return false;
|
||||
});
|
||||
// Find patch decoration if present
|
||||
bool is_patch = !deco_mgr->WhileEachDecoration(
|
||||
var_id, uint32_t(spv::Decoration::Patch), [](const Instruction& deco) {
|
||||
if (deco.opcode() != spv::Op::OpDecorate)
|
||||
assert(false && "unexpected decoration");
|
||||
return false;
|
||||
});
|
||||
// Compute offset and final type of reference. If no location found
|
||||
// or any stored locations are live, return without removing stores.
|
||||
auto ptr_type = type_mgr->GetType(var->type_id())->AsPointer();
|
||||
assert(ptr_type && "unexpected var type");
|
||||
auto var_type = ptr_type->pointee_type();
|
||||
uint32_t ref_loc = start_loc;
|
||||
auto curr_type = var_type;
|
||||
if (ref->opcode() == spv::Op::OpAccessChain ||
|
||||
ref->opcode() == spv::Op::OpInBoundsAccessChain) {
|
||||
live_mgr->AnalyzeAccessChainLoc(ref, &curr_type, &ref_loc, &no_loc,
|
||||
is_patch, /* input */ false);
|
||||
}
|
||||
if (no_loc || AnyLocsAreLive(ref_loc, live_mgr->GetLocSize(curr_type)))
|
||||
return;
|
||||
// Kill all stores based on this reference
|
||||
KillAllStoresOfRef(ref);
|
||||
}
|
||||
|
||||
void EliminateDeadOutputStoresPass::KillAllDeadStoresOfBuiltinRef(
|
||||
Instruction* ref, Instruction* var) {
|
||||
auto deco_mgr = context()->get_decoration_mgr();
|
||||
auto def_use_mgr = context()->get_def_use_mgr();
|
||||
auto type_mgr = context()->get_type_mgr();
|
||||
auto live_mgr = context()->get_liveness_mgr();
|
||||
// Search for builtin decoration of base variable
|
||||
uint32_t builtin = uint32_t(spv::BuiltIn::Max);
|
||||
auto var_id = var->result_id();
|
||||
(void)deco_mgr->WhileEachDecoration(
|
||||
var_id, uint32_t(spv::Decoration::BuiltIn),
|
||||
[&builtin](const Instruction& deco) {
|
||||
assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
|
||||
builtin = deco.GetSingleWordInOperand(kOpDecorateBuiltInLiteralInIdx);
|
||||
return false;
|
||||
});
|
||||
// If analyzed builtin and not live, kill stores.
|
||||
if (builtin != uint32_t(spv::BuiltIn::Max)) {
|
||||
if (live_mgr->IsAnalyzedBuiltin(builtin) && !IsLiveBuiltin(builtin))
|
||||
KillAllStoresOfRef(ref);
|
||||
return;
|
||||
}
|
||||
// Search for builtin decoration on indexed member
|
||||
auto ref_op = ref->opcode();
|
||||
if (ref_op != spv::Op::OpAccessChain &&
|
||||
ref_op != spv::Op::OpInBoundsAccessChain) {
|
||||
return;
|
||||
}
|
||||
uint32_t in_idx = kOpAccessChainIdx0InIdx;
|
||||
analysis::Type* var_type = type_mgr->GetType(var->type_id());
|
||||
analysis::Pointer* ptr_type = var_type->AsPointer();
|
||||
auto curr_type = ptr_type->pointee_type();
|
||||
auto arr_type = curr_type->AsArray();
|
||||
if (arr_type) {
|
||||
curr_type = arr_type->element_type();
|
||||
++in_idx;
|
||||
}
|
||||
auto str_type = curr_type->AsStruct();
|
||||
auto str_type_id = type_mgr->GetId(str_type);
|
||||
auto member_idx_id = ref->GetSingleWordInOperand(in_idx);
|
||||
auto member_idx_inst = def_use_mgr->GetDef(member_idx_id);
|
||||
assert(member_idx_inst->opcode() == spv::Op::OpConstant &&
|
||||
"unexpected non-constant index");
|
||||
auto ac_idx = member_idx_inst->GetSingleWordInOperand(kOpConstantValueInIdx);
|
||||
(void)deco_mgr->WhileEachDecoration(
|
||||
str_type_id, uint32_t(spv::Decoration::BuiltIn),
|
||||
[ac_idx, &builtin](const Instruction& deco) {
|
||||
assert(deco.opcode() == spv::Op::OpMemberDecorate &&
|
||||
"unexpected decoration");
|
||||
auto deco_idx =
|
||||
deco.GetSingleWordInOperand(kOpDecorateMemberMemberInIdx);
|
||||
if (deco_idx == ac_idx) {
|
||||
builtin =
|
||||
deco.GetSingleWordInOperand(kOpDecorateMemberBuiltInLiteralInIdx);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
assert(builtin != uint32_t(spv::BuiltIn::Max) && "builtin not found");
|
||||
// If analyzed builtin and not live, kill stores.
|
||||
if (live_mgr->IsAnalyzedBuiltin(builtin) && !IsLiveBuiltin(builtin))
|
||||
KillAllStoresOfRef(ref);
|
||||
}
|
||||
|
||||
Pass::Status EliminateDeadOutputStoresPass::DoDeadOutputStoreElimination() {
|
||||
// Current implementation only supports vert, tesc, tese, geom shaders
|
||||
auto stage = context()->GetStage();
|
||||
if (stage != spv::ExecutionModel::Vertex &&
|
||||
stage != spv::ExecutionModel::TessellationControl &&
|
||||
stage != spv::ExecutionModel::TessellationEvaluation &&
|
||||
stage != spv::ExecutionModel::Geometry)
|
||||
return Status::Failure;
|
||||
InitializeElimination();
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
|
||||
// Process all output variables
|
||||
for (auto& var : context()->types_values()) {
|
||||
if (var.opcode() != spv::Op::OpVariable) {
|
||||
continue;
|
||||
}
|
||||
analysis::Type* var_type = type_mgr->GetType(var.type_id());
|
||||
analysis::Pointer* ptr_type = var_type->AsPointer();
|
||||
if (ptr_type->storage_class() != spv::StorageClass::Output) {
|
||||
continue;
|
||||
}
|
||||
// If builtin decoration on variable, process as builtin.
|
||||
auto var_id = var.result_id();
|
||||
bool is_builtin = false;
|
||||
if (deco_mgr->HasDecoration(var_id, uint32_t(spv::Decoration::BuiltIn))) {
|
||||
is_builtin = true;
|
||||
} else {
|
||||
// If interface block with builtin members, process as builtin.
|
||||
// Strip off outer array type if present.
|
||||
auto curr_type = ptr_type->pointee_type();
|
||||
auto arr_type = curr_type->AsArray();
|
||||
if (arr_type) curr_type = arr_type->element_type();
|
||||
auto str_type = curr_type->AsStruct();
|
||||
if (str_type) {
|
||||
auto str_type_id = type_mgr->GetId(str_type);
|
||||
if (deco_mgr->HasDecoration(str_type_id,
|
||||
uint32_t(spv::Decoration::BuiltIn)))
|
||||
is_builtin = true;
|
||||
}
|
||||
}
|
||||
// For each store or access chain using var, if dead builtin or all its
|
||||
// locations are dead, kill store or all access chain's stores
|
||||
def_use_mgr->ForEachUser(
|
||||
var_id, [this, &var, is_builtin](Instruction* user) {
|
||||
auto op = user->opcode();
|
||||
if (op == spv::Op::OpEntryPoint || op == spv::Op::OpName ||
|
||||
op == spv::Op::OpDecorate)
|
||||
return;
|
||||
if (is_builtin)
|
||||
KillAllDeadStoresOfBuiltinRef(user, &var);
|
||||
else
|
||||
KillAllDeadStoresOfLocRef(user, &var);
|
||||
});
|
||||
}
|
||||
for (auto& kinst : kill_list_) context()->KillInst(kinst);
|
||||
|
||||
return kill_list_.empty() ? Status::SuccessWithoutChange
|
||||
: Status::SuccessWithChange;
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
87
3rdparty/spirv-tools/source/opt/eliminate_dead_output_stores_pass.h
vendored
Normal file
87
3rdparty/spirv-tools/source/opt/eliminate_dead_output_stores_pass.h
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2022 The Khronos Group Inc.
|
||||
// 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SOURCE_OPT_ELIMINATE_DEAD_OUTPUT_STORES_H_
|
||||
#define SOURCE_OPT_ELIMINATE_DEAD_OUTPUT_STORES_H_
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/opt/module.h"
|
||||
#include "source/opt/pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// See optimizer.hpp for documentation.
|
||||
class EliminateDeadOutputStoresPass : public Pass {
|
||||
public:
|
||||
explicit EliminateDeadOutputStoresPass(
|
||||
std::unordered_set<uint32_t>* live_locs,
|
||||
std::unordered_set<uint32_t>* live_builtins)
|
||||
: live_locs_(live_locs), live_builtins_(live_builtins) {}
|
||||
|
||||
const char* name() const override { return "eliminate-dead-output-stores"; }
|
||||
Status Process() override;
|
||||
|
||||
// Return the mask of preserved Analyses.
|
||||
IRContext::Analysis GetPreservedAnalyses() override {
|
||||
return IRContext::kAnalysisDefUse |
|
||||
IRContext::kAnalysisInstrToBlockMapping |
|
||||
IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG |
|
||||
IRContext::kAnalysisDominatorAnalysis |
|
||||
IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
|
||||
IRContext::kAnalysisConstants | IRContext::kAnalysisTypes;
|
||||
}
|
||||
|
||||
private:
|
||||
// Initialize elimination
|
||||
void InitializeElimination();
|
||||
|
||||
// Do dead output store analysis
|
||||
Status DoDeadOutputStoreAnalysis();
|
||||
|
||||
// Do dead output store analysis
|
||||
Status DoDeadOutputStoreElimination();
|
||||
|
||||
// Mark all locations live
|
||||
void MarkAllLocsLive();
|
||||
|
||||
// Kill all stores resulting from |ref|.
|
||||
void KillAllStoresOfRef(Instruction* ref);
|
||||
|
||||
// Kill all dead stores resulting from |user| of loc-based |var|.
|
||||
void KillAllDeadStoresOfLocRef(Instruction* user, Instruction* var);
|
||||
|
||||
// Kill all dead stores resulting from |user| of builtin |var|.
|
||||
void KillAllDeadStoresOfBuiltinRef(Instruction* user, Instruction* var);
|
||||
|
||||
// Return true if any of |count| locations starting at location |start| are
|
||||
// live.
|
||||
bool AnyLocsAreLive(uint32_t start, uint32_t count);
|
||||
|
||||
// Return true if builtin |bi| is live.
|
||||
bool IsLiveBuiltin(uint32_t bi);
|
||||
|
||||
std::unordered_set<uint32_t>* live_locs_;
|
||||
std::unordered_set<uint32_t>* live_builtins_;
|
||||
|
||||
std::vector<Instruction*> kill_list_;
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_OPT_ELIMINATE_DEAD_OUTPUT_STORES_H_
|
||||
@@ -36,7 +36,7 @@ void FeatureManager::AddExtensions(Module* module) {
|
||||
}
|
||||
|
||||
void FeatureManager::AddExtension(Instruction* ext) {
|
||||
assert(ext->opcode() == SpvOpExtension &&
|
||||
assert(ext->opcode() == spv::Op::OpExtension &&
|
||||
"Expecting an extension instruction.");
|
||||
|
||||
const std::string name = ext->GetInOperand(0u).AsString();
|
||||
@@ -51,27 +51,27 @@ void FeatureManager::RemoveExtension(Extension ext) {
|
||||
extensions_.Remove(ext);
|
||||
}
|
||||
|
||||
void FeatureManager::AddCapability(SpvCapability cap) {
|
||||
void FeatureManager::AddCapability(spv::Capability cap) {
|
||||
if (capabilities_.Contains(cap)) return;
|
||||
|
||||
capabilities_.Add(cap);
|
||||
|
||||
spv_operand_desc desc = {};
|
||||
if (SPV_SUCCESS ==
|
||||
grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
|
||||
if (SPV_SUCCESS == grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
|
||||
uint32_t(cap), &desc)) {
|
||||
CapabilitySet(desc->numCapabilities, desc->capabilities)
|
||||
.ForEach([this](SpvCapability c) { AddCapability(c); });
|
||||
.ForEach([this](spv::Capability c) { AddCapability(c); });
|
||||
}
|
||||
}
|
||||
|
||||
void FeatureManager::RemoveCapability(SpvCapability cap) {
|
||||
void FeatureManager::RemoveCapability(spv::Capability cap) {
|
||||
if (!capabilities_.Contains(cap)) return;
|
||||
capabilities_.Remove(cap);
|
||||
}
|
||||
|
||||
void FeatureManager::AddCapabilities(Module* module) {
|
||||
for (Instruction& inst : module->capabilities()) {
|
||||
AddCapability(static_cast<SpvCapability>(inst.GetSingleWordInOperand(0)));
|
||||
AddCapability(static_cast<spv::Capability>(inst.GetSingleWordInOperand(0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ class FeatureManager {
|
||||
void RemoveExtension(Extension extension);
|
||||
|
||||
// Returns true if |cap| is an enabled capability in the module.
|
||||
bool HasCapability(SpvCapability cap) const {
|
||||
bool HasCapability(spv::Capability cap) const {
|
||||
return capabilities_.Contains(cap);
|
||||
}
|
||||
|
||||
// Removes the given |capability| from the current FeatureManager.
|
||||
void RemoveCapability(SpvCapability capability);
|
||||
void RemoveCapability(spv::Capability capability);
|
||||
|
||||
// Analyzes |module| and records enabled extensions and capabilities.
|
||||
void Analyze(Module* module);
|
||||
@@ -66,7 +66,7 @@ class FeatureManager {
|
||||
|
||||
// Adds the given |capability| and all implied capabilities into the current
|
||||
// FeatureManager.
|
||||
void AddCapability(SpvCapability capability);
|
||||
void AddCapability(spv::Capability capability);
|
||||
|
||||
// Add the extension |ext| to the feature manager.
|
||||
void AddExtension(Instruction* ext);
|
||||
|
||||
@@ -29,7 +29,7 @@ Pass::Status FixFuncCallArgumentsPass::Process() {
|
||||
if (ModuleHasASingleFunction()) return Status::SuccessWithoutChange;
|
||||
for (auto& func : *get_module()) {
|
||||
func.ForEachInst([this, &modified](Instruction* inst) {
|
||||
if (inst->opcode() == SpvOpFunctionCall) {
|
||||
if (inst->opcode() == spv::Op::OpFunctionCall) {
|
||||
modified |= FixFuncCallArguments(inst);
|
||||
}
|
||||
});
|
||||
@@ -44,7 +44,7 @@ bool FixFuncCallArgumentsPass::FixFuncCallArguments(
|
||||
Operand& op = func_call_inst->GetInOperand(i);
|
||||
if (op.type != SPV_OPERAND_TYPE_ID) continue;
|
||||
Instruction* operand_inst = get_def_use_mgr()->GetDef(op.AsId());
|
||||
if (operand_inst->opcode() == SpvOpAccessChain) {
|
||||
if (operand_inst->opcode() == spv::Op::OpAccessChain) {
|
||||
uint32_t var_id =
|
||||
ReplaceAccessChainFuncCallArguments(func_call_inst, operand_inst);
|
||||
func_call_inst->SetInOperand(i, {var_id});
|
||||
@@ -71,10 +71,11 @@ uint32_t FixFuncCallArgumentsPass::ReplaceAccessChainFuncCallArguments(
|
||||
Instruction* op_type =
|
||||
get_def_use_mgr()->GetDef(op_ptr_type->GetSingleWordInOperand(1));
|
||||
uint32_t varType = context()->get_type_mgr()->FindPointerToType(
|
||||
op_type->result_id(), SpvStorageClassFunction);
|
||||
op_type->result_id(), spv::StorageClass::Function);
|
||||
// Create new variable
|
||||
builder.SetInsertPoint(variable_insertion_point);
|
||||
Instruction* var = builder.AddVariable(varType, SpvStorageClassFunction);
|
||||
Instruction* var =
|
||||
builder.AddVariable(varType, uint32_t(spv::StorageClass::Function));
|
||||
// Load access chain to the new variable before function call
|
||||
builder.SetInsertPoint(func_call_inst);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Pass::Status FixStorageClass::Process() {
|
||||
bool modified = false;
|
||||
|
||||
get_module()->ForEachInst([this, &modified](Instruction* inst) {
|
||||
if (inst->opcode() == SpvOpVariable) {
|
||||
if (inst->opcode() == spv::Op::OpVariable) {
|
||||
std::set<uint32_t> seen;
|
||||
std::vector<std::pair<Instruction*, uint32_t>> uses;
|
||||
get_def_use_mgr()->ForEachUse(inst,
|
||||
@@ -37,7 +37,7 @@ Pass::Status FixStorageClass::Process() {
|
||||
for (auto& use : uses) {
|
||||
modified |= PropagateStorageClass(
|
||||
use.first,
|
||||
static_cast<SpvStorageClass>(inst->GetSingleWordInOperand(0)),
|
||||
static_cast<spv::StorageClass>(inst->GetSingleWordInOperand(0)),
|
||||
&seen);
|
||||
assert(seen.empty() && "Seen was not properly reset.");
|
||||
modified |=
|
||||
@@ -50,14 +50,14 @@ Pass::Status FixStorageClass::Process() {
|
||||
}
|
||||
|
||||
bool FixStorageClass::PropagateStorageClass(Instruction* inst,
|
||||
SpvStorageClass storage_class,
|
||||
spv::StorageClass storage_class,
|
||||
std::set<uint32_t>* seen) {
|
||||
if (!IsPointerResultType(inst)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsPointerToStorageClass(inst, storage_class)) {
|
||||
if (inst->opcode() == SpvOpPhi) {
|
||||
if (inst->opcode() == spv::Op::OpPhi) {
|
||||
if (!seen->insert(inst->result_id()).second) {
|
||||
return false;
|
||||
}
|
||||
@@ -71,34 +71,34 @@ bool FixStorageClass::PropagateStorageClass(Instruction* inst,
|
||||
modified |= PropagateStorageClass(use, storage_class, seen);
|
||||
}
|
||||
|
||||
if (inst->opcode() == SpvOpPhi) {
|
||||
if (inst->opcode() == spv::Op::OpPhi) {
|
||||
seen->erase(inst->result_id());
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpCopyObject:
|
||||
case SpvOpPhi:
|
||||
case SpvOpSelect:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpCopyObject:
|
||||
case spv::Op::OpPhi:
|
||||
case spv::Op::OpSelect:
|
||||
FixInstructionStorageClass(inst, storage_class, seen);
|
||||
return true;
|
||||
case SpvOpFunctionCall:
|
||||
case spv::Op::OpFunctionCall:
|
||||
// We cannot be sure of the actual connection between the storage class
|
||||
// of the parameter and the storage class of the result, so we should not
|
||||
// do anything. If the result type needs to be fixed, the function call
|
||||
// should be inlined.
|
||||
return false;
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpLoad:
|
||||
case SpvOpStore:
|
||||
case SpvOpCopyMemory:
|
||||
case SpvOpCopyMemorySized:
|
||||
case SpvOpVariable:
|
||||
case SpvOpBitcast:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
case spv::Op::OpLoad:
|
||||
case spv::Op::OpStore:
|
||||
case spv::Op::OpCopyMemory:
|
||||
case spv::Op::OpCopyMemorySized:
|
||||
case spv::Op::OpVariable:
|
||||
case spv::Op::OpBitcast:
|
||||
// Nothing to change for these opcode. The result type is the same
|
||||
// regardless of the storage class of the operand.
|
||||
return false;
|
||||
@@ -109,9 +109,9 @@ bool FixStorageClass::PropagateStorageClass(Instruction* inst,
|
||||
}
|
||||
}
|
||||
|
||||
void FixStorageClass::FixInstructionStorageClass(Instruction* inst,
|
||||
SpvStorageClass storage_class,
|
||||
std::set<uint32_t>* seen) {
|
||||
void FixStorageClass::FixInstructionStorageClass(
|
||||
Instruction* inst, spv::StorageClass storage_class,
|
||||
std::set<uint32_t>* seen) {
|
||||
assert(IsPointerResultType(inst) &&
|
||||
"The result type of the instruction must be a pointer.");
|
||||
|
||||
@@ -126,10 +126,10 @@ void FixStorageClass::FixInstructionStorageClass(Instruction* inst,
|
||||
}
|
||||
|
||||
void FixStorageClass::ChangeResultStorageClass(
|
||||
Instruction* inst, SpvStorageClass storage_class) const {
|
||||
Instruction* inst, spv::StorageClass storage_class) const {
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
Instruction* result_type_inst = get_def_use_mgr()->GetDef(inst->type_id());
|
||||
assert(result_type_inst->opcode() == SpvOpTypePointer);
|
||||
assert(result_type_inst->opcode() == spv::Op::OpTypePointer);
|
||||
uint32_t pointee_type_id = result_type_inst->GetSingleWordInOperand(1);
|
||||
uint32_t new_result_type_id =
|
||||
type_mgr->FindPointerToType(pointee_type_id, storage_class);
|
||||
@@ -147,7 +147,7 @@ bool FixStorageClass::IsPointerResultType(Instruction* inst) {
|
||||
}
|
||||
|
||||
bool FixStorageClass::IsPointerToStorageClass(Instruction* inst,
|
||||
SpvStorageClass storage_class) {
|
||||
spv::StorageClass storage_class) {
|
||||
analysis::TypeManager* type_mgr = context()->get_type_mgr();
|
||||
analysis::Type* pType = type_mgr->GetType(inst->type_id());
|
||||
const analysis::Pointer* result_type = pType->AsPointer();
|
||||
@@ -180,39 +180,39 @@ bool FixStorageClass::PropagateType(Instruction* inst, uint32_t type_id,
|
||||
// particular type, then we want find that type.
|
||||
uint32_t new_type_id = 0;
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
if (op_idx == 2) {
|
||||
new_type_id = WalkAccessChainType(inst, type_id);
|
||||
}
|
||||
break;
|
||||
case SpvOpCopyObject:
|
||||
case spv::Op::OpCopyObject:
|
||||
new_type_id = type_id;
|
||||
break;
|
||||
case SpvOpPhi:
|
||||
case spv::Op::OpPhi:
|
||||
if (seen->insert(inst->result_id()).second) {
|
||||
new_type_id = type_id;
|
||||
}
|
||||
break;
|
||||
case SpvOpSelect:
|
||||
case spv::Op::OpSelect:
|
||||
if (op_idx > 2) {
|
||||
new_type_id = type_id;
|
||||
}
|
||||
break;
|
||||
case SpvOpFunctionCall:
|
||||
case spv::Op::OpFunctionCall:
|
||||
// We cannot be sure of the actual connection between the type
|
||||
// of the parameter and the type of the result, so we should not
|
||||
// do anything. If the result type needs to be fixed, the function call
|
||||
// should be inlined.
|
||||
return false;
|
||||
case SpvOpLoad: {
|
||||
case spv::Op::OpLoad: {
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
new_type_id = type_inst->GetSingleWordInOperand(1);
|
||||
break;
|
||||
}
|
||||
case SpvOpStore: {
|
||||
case spv::Op::OpStore: {
|
||||
uint32_t obj_id = inst->GetSingleWordInOperand(1);
|
||||
Instruction* obj_inst = get_def_use_mgr()->GetDef(obj_id);
|
||||
uint32_t obj_type_id = obj_inst->type_id();
|
||||
@@ -237,18 +237,18 @@ bool FixStorageClass::PropagateType(Instruction* inst, uint32_t type_id,
|
||||
context()->UpdateDefUse(inst);
|
||||
}
|
||||
} break;
|
||||
case SpvOpCopyMemory:
|
||||
case SpvOpCopyMemorySized:
|
||||
case spv::Op::OpCopyMemory:
|
||||
case spv::Op::OpCopyMemorySized:
|
||||
// TODO: May need to expand the copy as we do with the stores.
|
||||
break;
|
||||
case SpvOpCompositeConstruct:
|
||||
case SpvOpCompositeExtract:
|
||||
case SpvOpCompositeInsert:
|
||||
case spv::Op::OpCompositeConstruct:
|
||||
case spv::Op::OpCompositeExtract:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
// TODO: DXC does not seem to generate code that will require changes to
|
||||
// these opcode. The can be implemented when they come up.
|
||||
break;
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpBitcast:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
case spv::Op::OpBitcast:
|
||||
// Nothing to change for these opcode. The result type is the same
|
||||
// regardless of the type of the operand.
|
||||
return false;
|
||||
@@ -278,7 +278,7 @@ bool FixStorageClass::PropagateType(Instruction* inst, uint32_t type_id,
|
||||
PropagateType(use.first, new_type_id, use.second, seen);
|
||||
}
|
||||
|
||||
if (inst->opcode() == SpvOpPhi) {
|
||||
if (inst->opcode() == spv::Op::OpPhi) {
|
||||
seen->erase(inst->result_id());
|
||||
}
|
||||
}
|
||||
@@ -288,12 +288,12 @@ bool FixStorageClass::PropagateType(Instruction* inst, uint32_t type_id,
|
||||
uint32_t FixStorageClass::WalkAccessChainType(Instruction* inst, uint32_t id) {
|
||||
uint32_t start_idx = 0;
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
start_idx = 1;
|
||||
break;
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
start_idx = 2;
|
||||
break;
|
||||
default:
|
||||
@@ -302,19 +302,19 @@ uint32_t FixStorageClass::WalkAccessChainType(Instruction* inst, uint32_t id) {
|
||||
}
|
||||
|
||||
Instruction* orig_type_inst = get_def_use_mgr()->GetDef(id);
|
||||
assert(orig_type_inst->opcode() == SpvOpTypePointer);
|
||||
assert(orig_type_inst->opcode() == spv::Op::OpTypePointer);
|
||||
id = orig_type_inst->GetSingleWordInOperand(1);
|
||||
|
||||
for (uint32_t i = start_idx; i < inst->NumInOperands(); ++i) {
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeVector:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
case spv::Op::OpTypeVector:
|
||||
id = type_inst->GetSingleWordInOperand(0);
|
||||
break;
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
const analysis::Constant* index_const =
|
||||
context()->get_constant_mgr()->FindDeclaredConstant(
|
||||
inst->GetSingleWordInOperand(i));
|
||||
@@ -330,8 +330,8 @@ uint32_t FixStorageClass::WalkAccessChainType(Instruction* inst, uint32_t id) {
|
||||
}
|
||||
|
||||
return context()->get_type_mgr()->FindPointerToType(
|
||||
id,
|
||||
static_cast<SpvStorageClass>(orig_type_inst->GetSingleWordInOperand(0)));
|
||||
id, static_cast<spv::StorageClass>(
|
||||
orig_type_inst->GetSingleWordInOperand(0)));
|
||||
}
|
||||
|
||||
// namespace opt
|
||||
|
||||
@@ -48,7 +48,7 @@ class FixStorageClass : public Pass {
|
||||
// appropriate, and propagates the change to the users of |inst| as well.
|
||||
// Returns true of any changes were made.
|
||||
// |seen| is used to track OpPhi instructions that should not be processed.
|
||||
bool PropagateStorageClass(Instruction* inst, SpvStorageClass storage_class,
|
||||
bool PropagateStorageClass(Instruction* inst, spv::StorageClass storage_class,
|
||||
std::set<uint32_t>* seen);
|
||||
|
||||
// Changes the storage class of the result of |inst| to |storage_class|.
|
||||
@@ -58,13 +58,13 @@ class FixStorageClass : public Pass {
|
||||
// |seen| is used to track OpPhi instructions that should not be processed by
|
||||
// |PropagateStorageClass|
|
||||
void FixInstructionStorageClass(Instruction* inst,
|
||||
SpvStorageClass storage_class,
|
||||
spv::StorageClass storage_class,
|
||||
std::set<uint32_t>* seen);
|
||||
|
||||
// Changes the storage class of the result of |inst| to |storage_class|. The
|
||||
// result type of |inst| must be a pointer.
|
||||
void ChangeResultStorageClass(Instruction* inst,
|
||||
SpvStorageClass storage_class) const;
|
||||
spv::StorageClass storage_class) const;
|
||||
|
||||
// Returns true if the result type of |inst| is a pointer.
|
||||
bool IsPointerResultType(Instruction* inst);
|
||||
@@ -72,7 +72,7 @@ class FixStorageClass : public Pass {
|
||||
// Returns true if the result of |inst| is a pointer to storage class
|
||||
// |storage_class|.
|
||||
bool IsPointerToStorageClass(Instruction* inst,
|
||||
SpvStorageClass storage_class);
|
||||
spv::StorageClass storage_class);
|
||||
|
||||
// Change |inst| to match that operand |op_idx| now has type |type_id|, and
|
||||
// adjust any uses of |inst| accordingly. Returns true if the code changed.
|
||||
|
||||
@@ -49,16 +49,16 @@ Pass::Status FlattenDecorationPass::Process() {
|
||||
// Rely on unordered_map::operator[] to create its entries on first access.
|
||||
for (const auto& inst : annotations) {
|
||||
switch (inst.opcode()) {
|
||||
case SpvOp::SpvOpDecorationGroup:
|
||||
case spv::Op::OpDecorationGroup:
|
||||
group_ids.insert(inst.result_id());
|
||||
break;
|
||||
case SpvOp::SpvOpGroupDecorate: {
|
||||
case spv::Op::OpGroupDecorate: {
|
||||
Words& words = normal_uses[inst.GetSingleWordInOperand(0)];
|
||||
for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
|
||||
words.push_back(inst.GetSingleWordInOperand(i));
|
||||
}
|
||||
} break;
|
||||
case SpvOp::SpvOpGroupMemberDecorate: {
|
||||
case spv::Op::OpGroupMemberDecorate: {
|
||||
Words& words = member_uses[inst.GetSingleWordInOperand(0)];
|
||||
for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
|
||||
words.push_back(inst.GetSingleWordInOperand(i));
|
||||
@@ -77,12 +77,12 @@ Pass::Status FlattenDecorationPass::Process() {
|
||||
// Should we replace this instruction?
|
||||
bool replace = false;
|
||||
switch (inst_iter->opcode()) {
|
||||
case SpvOp::SpvOpDecorationGroup:
|
||||
case SpvOp::SpvOpGroupDecorate:
|
||||
case SpvOp::SpvOpGroupMemberDecorate:
|
||||
case spv::Op::OpDecorationGroup:
|
||||
case spv::Op::OpGroupDecorate:
|
||||
case spv::Op::OpGroupMemberDecorate:
|
||||
replace = true;
|
||||
break;
|
||||
case SpvOp::SpvOpDecorate: {
|
||||
case spv::Op::OpDecorate: {
|
||||
// If this decoration targets a group, then replace it
|
||||
// by sets of normal and member decorations.
|
||||
const uint32_t group = inst_iter->GetSingleWordOperand(0);
|
||||
@@ -115,7 +115,7 @@ Pass::Status FlattenDecorationPass::Process() {
|
||||
operands.insert(operands.end(), decoration_operands_iter,
|
||||
inst_iter->end());
|
||||
std::unique_ptr<Instruction> new_inst(new Instruction(
|
||||
context(), SpvOp::SpvOpMemberDecorate, 0, 0, operands));
|
||||
context(), spv::Op::OpMemberDecorate, 0, 0, operands));
|
||||
inst_iter = inst_iter.InsertBefore(std::move(new_inst));
|
||||
++inst_iter;
|
||||
replace = true;
|
||||
@@ -146,7 +146,7 @@ Pass::Status FlattenDecorationPass::Process() {
|
||||
if (!group_ids.empty()) {
|
||||
for (auto debug_inst_iter = context()->debug2_begin();
|
||||
debug_inst_iter != context()->debug2_end();) {
|
||||
if (debug_inst_iter->opcode() == SpvOp::SpvOpName) {
|
||||
if (debug_inst_iter->opcode() == spv::Op::OpName) {
|
||||
const uint32_t target = debug_inst_iter->GetSingleWordOperand(0);
|
||||
if (group_ids.count(target)) {
|
||||
debug_inst_iter = debug_inst_iter.Erase();
|
||||
|
||||
207
3rdparty/spirv-tools/source/opt/fold.cpp
vendored
207
3rdparty/spirv-tools/source/opt/fold.cpp
vendored
@@ -42,23 +42,24 @@ namespace {
|
||||
|
||||
} // namespace
|
||||
|
||||
uint32_t InstructionFolder::UnaryOperate(SpvOp opcode, uint32_t operand) const {
|
||||
uint32_t InstructionFolder::UnaryOperate(spv::Op opcode,
|
||||
uint32_t operand) const {
|
||||
switch (opcode) {
|
||||
// Arthimetics
|
||||
case SpvOp::SpvOpSNegate: {
|
||||
case spv::Op::OpSNegate: {
|
||||
int32_t s_operand = static_cast<int32_t>(operand);
|
||||
if (s_operand == std::numeric_limits<int32_t>::min()) {
|
||||
return s_operand;
|
||||
}
|
||||
return -s_operand;
|
||||
}
|
||||
case SpvOp::SpvOpNot:
|
||||
case spv::Op::OpNot:
|
||||
return ~operand;
|
||||
case SpvOp::SpvOpLogicalNot:
|
||||
case spv::Op::OpLogicalNot:
|
||||
return !static_cast<bool>(operand);
|
||||
case SpvOp::SpvOpUConvert:
|
||||
case spv::Op::OpUConvert:
|
||||
return operand;
|
||||
case SpvOp::SpvOpSConvert:
|
||||
case spv::Op::OpSConvert:
|
||||
return operand;
|
||||
default:
|
||||
assert(false &&
|
||||
@@ -67,31 +68,31 @@ uint32_t InstructionFolder::UnaryOperate(SpvOp opcode, uint32_t operand) const {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
uint32_t InstructionFolder::BinaryOperate(spv::Op opcode, uint32_t a,
|
||||
uint32_t b) const {
|
||||
switch (opcode) {
|
||||
// Arthimetics
|
||||
case SpvOp::SpvOpIAdd:
|
||||
case spv::Op::OpIAdd:
|
||||
return a + b;
|
||||
case SpvOp::SpvOpISub:
|
||||
case spv::Op::OpISub:
|
||||
return a - b;
|
||||
case SpvOp::SpvOpIMul:
|
||||
case spv::Op::OpIMul:
|
||||
return a * b;
|
||||
case SpvOp::SpvOpUDiv:
|
||||
case spv::Op::OpUDiv:
|
||||
if (b != 0) {
|
||||
return a / b;
|
||||
} else {
|
||||
// Dividing by 0 is undefined, so we will just pick 0.
|
||||
return 0;
|
||||
}
|
||||
case SpvOp::SpvOpSDiv:
|
||||
case spv::Op::OpSDiv:
|
||||
if (b != 0u) {
|
||||
return (static_cast<int32_t>(a)) / (static_cast<int32_t>(b));
|
||||
} else {
|
||||
// Dividing by 0 is undefined, so we will just pick 0.
|
||||
return 0;
|
||||
}
|
||||
case SpvOp::SpvOpSRem: {
|
||||
case spv::Op::OpSRem: {
|
||||
// The sign of non-zero result comes from the first operand: a. This is
|
||||
// guaranteed by C++11 rules for integer division operator. The division
|
||||
// result is rounded toward zero, so the result of '%' has the sign of
|
||||
@@ -103,10 +104,10 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case SpvOp::SpvOpSMod: {
|
||||
case spv::Op::OpSMod: {
|
||||
// The sign of non-zero result comes from the second operand: b
|
||||
if (b != 0u) {
|
||||
int32_t rem = BinaryOperate(SpvOp::SpvOpSRem, a, b);
|
||||
int32_t rem = BinaryOperate(spv::Op::OpSRem, a, b);
|
||||
int32_t b_prim = static_cast<int32_t>(b);
|
||||
return (rem + b_prim) % b_prim;
|
||||
} else {
|
||||
@@ -114,7 +115,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case SpvOp::SpvOpUMod:
|
||||
case spv::Op::OpUMod:
|
||||
if (b != 0u) {
|
||||
return (a % b);
|
||||
} else {
|
||||
@@ -123,7 +124,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
}
|
||||
|
||||
// Shifting
|
||||
case SpvOp::SpvOpShiftRightLogical:
|
||||
case spv::Op::OpShiftRightLogical:
|
||||
if (b >= 32) {
|
||||
// This is undefined behaviour when |b| > 32. Choose 0 for consistency.
|
||||
// When |b| == 32, doing the shift in C++ in undefined, but the result
|
||||
@@ -131,7 +132,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
return 0;
|
||||
}
|
||||
return a >> b;
|
||||
case SpvOp::SpvOpShiftRightArithmetic:
|
||||
case spv::Op::OpShiftRightArithmetic:
|
||||
if (b > 32) {
|
||||
// This is undefined behaviour. Choose 0 for consistency.
|
||||
return 0;
|
||||
@@ -146,7 +147,7 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
}
|
||||
}
|
||||
return (static_cast<int32_t>(a)) >> b;
|
||||
case SpvOp::SpvOpShiftLeftLogical:
|
||||
case spv::Op::OpShiftLeftLogical:
|
||||
if (b >= 32) {
|
||||
// This is undefined behaviour when |b| > 32. Choose 0 for consistency.
|
||||
// When |b| == 32, doing the shift in C++ in undefined, but the result
|
||||
@@ -156,43 +157,43 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
return a << b;
|
||||
|
||||
// Bitwise operations
|
||||
case SpvOp::SpvOpBitwiseOr:
|
||||
case spv::Op::OpBitwiseOr:
|
||||
return a | b;
|
||||
case SpvOp::SpvOpBitwiseAnd:
|
||||
case spv::Op::OpBitwiseAnd:
|
||||
return a & b;
|
||||
case SpvOp::SpvOpBitwiseXor:
|
||||
case spv::Op::OpBitwiseXor:
|
||||
return a ^ b;
|
||||
|
||||
// Logical
|
||||
case SpvOp::SpvOpLogicalEqual:
|
||||
case spv::Op::OpLogicalEqual:
|
||||
return (static_cast<bool>(a)) == (static_cast<bool>(b));
|
||||
case SpvOp::SpvOpLogicalNotEqual:
|
||||
case spv::Op::OpLogicalNotEqual:
|
||||
return (static_cast<bool>(a)) != (static_cast<bool>(b));
|
||||
case SpvOp::SpvOpLogicalOr:
|
||||
case spv::Op::OpLogicalOr:
|
||||
return (static_cast<bool>(a)) || (static_cast<bool>(b));
|
||||
case SpvOp::SpvOpLogicalAnd:
|
||||
case spv::Op::OpLogicalAnd:
|
||||
return (static_cast<bool>(a)) && (static_cast<bool>(b));
|
||||
|
||||
// Comparison
|
||||
case SpvOp::SpvOpIEqual:
|
||||
case spv::Op::OpIEqual:
|
||||
return a == b;
|
||||
case SpvOp::SpvOpINotEqual:
|
||||
case spv::Op::OpINotEqual:
|
||||
return a != b;
|
||||
case SpvOp::SpvOpULessThan:
|
||||
case spv::Op::OpULessThan:
|
||||
return a < b;
|
||||
case SpvOp::SpvOpSLessThan:
|
||||
case spv::Op::OpSLessThan:
|
||||
return (static_cast<int32_t>(a)) < (static_cast<int32_t>(b));
|
||||
case SpvOp::SpvOpUGreaterThan:
|
||||
case spv::Op::OpUGreaterThan:
|
||||
return a > b;
|
||||
case SpvOp::SpvOpSGreaterThan:
|
||||
case spv::Op::OpSGreaterThan:
|
||||
return (static_cast<int32_t>(a)) > (static_cast<int32_t>(b));
|
||||
case SpvOp::SpvOpULessThanEqual:
|
||||
case spv::Op::OpULessThanEqual:
|
||||
return a <= b;
|
||||
case SpvOp::SpvOpSLessThanEqual:
|
||||
case spv::Op::OpSLessThanEqual:
|
||||
return (static_cast<int32_t>(a)) <= (static_cast<int32_t>(b));
|
||||
case SpvOp::SpvOpUGreaterThanEqual:
|
||||
case spv::Op::OpUGreaterThanEqual:
|
||||
return a >= b;
|
||||
case SpvOp::SpvOpSGreaterThanEqual:
|
||||
case spv::Op::OpSGreaterThanEqual:
|
||||
return (static_cast<int32_t>(a)) >= (static_cast<int32_t>(b));
|
||||
default:
|
||||
assert(false &&
|
||||
@@ -201,10 +202,10 @@ uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t InstructionFolder::TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b,
|
||||
uint32_t c) const {
|
||||
uint32_t InstructionFolder::TernaryOperate(spv::Op opcode, uint32_t a,
|
||||
uint32_t b, uint32_t c) const {
|
||||
switch (opcode) {
|
||||
case SpvOp::SpvOpSelect:
|
||||
case spv::Op::OpSelect:
|
||||
return (static_cast<bool>(a)) ? b : c;
|
||||
default:
|
||||
assert(false &&
|
||||
@@ -214,7 +215,7 @@ uint32_t InstructionFolder::TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b,
|
||||
}
|
||||
|
||||
uint32_t InstructionFolder::OperateWords(
|
||||
SpvOp opcode, const std::vector<uint32_t>& operand_words) const {
|
||||
spv::Op opcode, const std::vector<uint32_t>& operand_words) const {
|
||||
switch (operand_words.size()) {
|
||||
case 1:
|
||||
return UnaryOperate(opcode, operand_words.front());
|
||||
@@ -233,7 +234,7 @@ bool InstructionFolder::FoldInstructionInternal(Instruction* inst) const {
|
||||
auto identity_map = [](uint32_t id) { return id; };
|
||||
Instruction* folded_inst = FoldInstructionToConstant(inst, identity_map);
|
||||
if (folded_inst != nullptr) {
|
||||
inst->SetOpcode(SpvOpCopyObject);
|
||||
inst->SetOpcode(spv::Op::OpCopyObject);
|
||||
inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {folded_inst->result_id()}}});
|
||||
return true;
|
||||
}
|
||||
@@ -256,7 +257,7 @@ bool InstructionFolder::FoldInstructionInternal(Instruction* inst) const {
|
||||
// result in 32 bit word. Scalar constants with longer than 32-bit width are
|
||||
// not accepted in this function.
|
||||
uint32_t InstructionFolder::FoldScalars(
|
||||
SpvOp opcode,
|
||||
spv::Op opcode,
|
||||
const std::vector<const analysis::Constant*>& operands) const {
|
||||
assert(IsFoldableOpcode(opcode) &&
|
||||
"Unhandled instruction opcode in FoldScalars");
|
||||
@@ -282,7 +283,7 @@ uint32_t InstructionFolder::FoldScalars(
|
||||
bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map,
|
||||
uint32_t* result) const {
|
||||
SpvOp opcode = inst->opcode();
|
||||
spv::Op opcode = inst->opcode();
|
||||
analysis::ConstantManager* const_manger = context_->get_constant_mgr();
|
||||
|
||||
uint32_t ids[2];
|
||||
@@ -300,7 +301,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
|
||||
switch (opcode) {
|
||||
// Arthimetics
|
||||
case SpvOp::SpvOpIMul:
|
||||
case spv::Op::OpIMul:
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
if (constants[i] != nullptr && constants[i]->IsZero()) {
|
||||
*result = 0;
|
||||
@@ -308,11 +309,11 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpUDiv:
|
||||
case SpvOp::SpvOpSDiv:
|
||||
case SpvOp::SpvOpSRem:
|
||||
case SpvOp::SpvOpSMod:
|
||||
case SpvOp::SpvOpUMod:
|
||||
case spv::Op::OpUDiv:
|
||||
case spv::Op::OpSDiv:
|
||||
case spv::Op::OpSRem:
|
||||
case spv::Op::OpSMod:
|
||||
case spv::Op::OpUMod:
|
||||
// This changes undefined behaviour (ie divide by 0) into a 0.
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
if (constants[i] != nullptr && constants[i]->IsZero()) {
|
||||
@@ -323,8 +324,8 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
break;
|
||||
|
||||
// Shifting
|
||||
case SpvOp::SpvOpShiftRightLogical:
|
||||
case SpvOp::SpvOpShiftLeftLogical:
|
||||
case spv::Op::OpShiftRightLogical:
|
||||
case spv::Op::OpShiftLeftLogical:
|
||||
if (constants[1] != nullptr) {
|
||||
// When shifting by a value larger than the size of the result, the
|
||||
// result is undefined. We are setting the undefined behaviour to a
|
||||
@@ -339,7 +340,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
break;
|
||||
|
||||
// Bitwise operations
|
||||
case SpvOp::SpvOpBitwiseOr:
|
||||
case spv::Op::OpBitwiseOr:
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
if (constants[i] != nullptr) {
|
||||
// TODO: Change the mask against a value based on the bit width of the
|
||||
@@ -353,7 +354,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpBitwiseAnd:
|
||||
case spv::Op::OpBitwiseAnd:
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
if (constants[i] != nullptr) {
|
||||
if (constants[i]->IsZero()) {
|
||||
@@ -365,7 +366,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
break;
|
||||
|
||||
// Comparison
|
||||
case SpvOp::SpvOpULessThan:
|
||||
case spv::Op::OpULessThan:
|
||||
if (constants[0] != nullptr &&
|
||||
constants[0]->GetU32BitValue() == UINT32_MAX) {
|
||||
*result = false;
|
||||
@@ -376,7 +377,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpSLessThan:
|
||||
case spv::Op::OpSLessThan:
|
||||
if (constants[0] != nullptr &&
|
||||
constants[0]->GetS32BitValue() == INT32_MAX) {
|
||||
*result = false;
|
||||
@@ -388,7 +389,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpUGreaterThan:
|
||||
case spv::Op::OpUGreaterThan:
|
||||
if (constants[0] != nullptr && constants[0]->IsZero()) {
|
||||
*result = false;
|
||||
return true;
|
||||
@@ -399,7 +400,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpSGreaterThan:
|
||||
case spv::Op::OpSGreaterThan:
|
||||
if (constants[0] != nullptr &&
|
||||
constants[0]->GetS32BitValue() == INT32_MIN) {
|
||||
*result = false;
|
||||
@@ -411,7 +412,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpULessThanEqual:
|
||||
case spv::Op::OpULessThanEqual:
|
||||
if (constants[0] != nullptr && constants[0]->IsZero()) {
|
||||
*result = true;
|
||||
return true;
|
||||
@@ -422,7 +423,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpSLessThanEqual:
|
||||
case spv::Op::OpSLessThanEqual:
|
||||
if (constants[0] != nullptr &&
|
||||
constants[0]->GetS32BitValue() == INT32_MIN) {
|
||||
*result = true;
|
||||
@@ -434,7 +435,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpUGreaterThanEqual:
|
||||
case spv::Op::OpUGreaterThanEqual:
|
||||
if (constants[0] != nullptr &&
|
||||
constants[0]->GetU32BitValue() == UINT32_MAX) {
|
||||
*result = true;
|
||||
@@ -445,7 +446,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpSGreaterThanEqual:
|
||||
case spv::Op::OpSGreaterThanEqual:
|
||||
if (constants[0] != nullptr &&
|
||||
constants[0]->GetS32BitValue() == INT32_MAX) {
|
||||
*result = true;
|
||||
@@ -466,7 +467,7 @@ bool InstructionFolder::FoldBinaryIntegerOpToConstant(
|
||||
bool InstructionFolder::FoldBinaryBooleanOpToConstant(
|
||||
Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map,
|
||||
uint32_t* result) const {
|
||||
SpvOp opcode = inst->opcode();
|
||||
spv::Op opcode = inst->opcode();
|
||||
analysis::ConstantManager* const_manger = context_->get_constant_mgr();
|
||||
|
||||
uint32_t ids[2];
|
||||
@@ -484,7 +485,7 @@ bool InstructionFolder::FoldBinaryBooleanOpToConstant(
|
||||
|
||||
switch (opcode) {
|
||||
// Logical
|
||||
case SpvOp::SpvOpLogicalOr:
|
||||
case spv::Op::OpLogicalOr:
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
if (constants[i] != nullptr) {
|
||||
if (constants[i]->value()) {
|
||||
@@ -494,7 +495,7 @@ bool InstructionFolder::FoldBinaryBooleanOpToConstant(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SpvOp::SpvOpLogicalAnd:
|
||||
case spv::Op::OpLogicalAnd:
|
||||
for (uint32_t i = 0; i < 2; i++) {
|
||||
if (constants[i] != nullptr) {
|
||||
if (!constants[i]->value()) {
|
||||
@@ -526,7 +527,7 @@ bool InstructionFolder::FoldIntegerOpToConstant(
|
||||
}
|
||||
|
||||
std::vector<uint32_t> InstructionFolder::FoldVectors(
|
||||
SpvOp opcode, uint32_t num_dims,
|
||||
spv::Op opcode, uint32_t num_dims,
|
||||
const std::vector<const analysis::Constant*>& operands) const {
|
||||
assert(IsFoldableOpcode(opcode) &&
|
||||
"Unhandled instruction opcode in FoldVectors");
|
||||
@@ -570,44 +571,44 @@ std::vector<uint32_t> InstructionFolder::FoldVectors(
|
||||
return result;
|
||||
}
|
||||
|
||||
bool InstructionFolder::IsFoldableOpcode(SpvOp opcode) const {
|
||||
bool InstructionFolder::IsFoldableOpcode(spv::Op opcode) const {
|
||||
// NOTE: Extend to more opcodes as new cases are handled in the folder
|
||||
// functions.
|
||||
switch (opcode) {
|
||||
case SpvOp::SpvOpBitwiseAnd:
|
||||
case SpvOp::SpvOpBitwiseOr:
|
||||
case SpvOp::SpvOpBitwiseXor:
|
||||
case SpvOp::SpvOpIAdd:
|
||||
case SpvOp::SpvOpIEqual:
|
||||
case SpvOp::SpvOpIMul:
|
||||
case SpvOp::SpvOpINotEqual:
|
||||
case SpvOp::SpvOpISub:
|
||||
case SpvOp::SpvOpLogicalAnd:
|
||||
case SpvOp::SpvOpLogicalEqual:
|
||||
case SpvOp::SpvOpLogicalNot:
|
||||
case SpvOp::SpvOpLogicalNotEqual:
|
||||
case SpvOp::SpvOpLogicalOr:
|
||||
case SpvOp::SpvOpNot:
|
||||
case SpvOp::SpvOpSDiv:
|
||||
case SpvOp::SpvOpSelect:
|
||||
case SpvOp::SpvOpSGreaterThan:
|
||||
case SpvOp::SpvOpSGreaterThanEqual:
|
||||
case SpvOp::SpvOpShiftLeftLogical:
|
||||
case SpvOp::SpvOpShiftRightArithmetic:
|
||||
case SpvOp::SpvOpShiftRightLogical:
|
||||
case SpvOp::SpvOpSLessThan:
|
||||
case SpvOp::SpvOpSLessThanEqual:
|
||||
case SpvOp::SpvOpSMod:
|
||||
case SpvOp::SpvOpSNegate:
|
||||
case SpvOp::SpvOpSRem:
|
||||
case SpvOp::SpvOpSConvert:
|
||||
case SpvOp::SpvOpUConvert:
|
||||
case SpvOp::SpvOpUDiv:
|
||||
case SpvOp::SpvOpUGreaterThan:
|
||||
case SpvOp::SpvOpUGreaterThanEqual:
|
||||
case SpvOp::SpvOpULessThan:
|
||||
case SpvOp::SpvOpULessThanEqual:
|
||||
case SpvOp::SpvOpUMod:
|
||||
case spv::Op::OpBitwiseAnd:
|
||||
case spv::Op::OpBitwiseOr:
|
||||
case spv::Op::OpBitwiseXor:
|
||||
case spv::Op::OpIAdd:
|
||||
case spv::Op::OpIEqual:
|
||||
case spv::Op::OpIMul:
|
||||
case spv::Op::OpINotEqual:
|
||||
case spv::Op::OpISub:
|
||||
case spv::Op::OpLogicalAnd:
|
||||
case spv::Op::OpLogicalEqual:
|
||||
case spv::Op::OpLogicalNot:
|
||||
case spv::Op::OpLogicalNotEqual:
|
||||
case spv::Op::OpLogicalOr:
|
||||
case spv::Op::OpNot:
|
||||
case spv::Op::OpSDiv:
|
||||
case spv::Op::OpSelect:
|
||||
case spv::Op::OpSGreaterThan:
|
||||
case spv::Op::OpSGreaterThanEqual:
|
||||
case spv::Op::OpShiftLeftLogical:
|
||||
case spv::Op::OpShiftRightArithmetic:
|
||||
case spv::Op::OpShiftRightLogical:
|
||||
case spv::Op::OpSLessThan:
|
||||
case spv::Op::OpSLessThanEqual:
|
||||
case spv::Op::OpSMod:
|
||||
case spv::Op::OpSNegate:
|
||||
case spv::Op::OpSRem:
|
||||
case spv::Op::OpSConvert:
|
||||
case spv::Op::OpUConvert:
|
||||
case spv::Op::OpUDiv:
|
||||
case spv::Op::OpUGreaterThan:
|
||||
case spv::Op::OpUGreaterThanEqual:
|
||||
case spv::Op::OpULessThan:
|
||||
case spv::Op::OpULessThanEqual:
|
||||
case spv::Op::OpUMod:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -685,11 +686,11 @@ Instruction* InstructionFolder::FoldInstructionToConstant(
|
||||
|
||||
bool InstructionFolder::IsFoldableType(Instruction* type_inst) const {
|
||||
// Support 32-bit integers.
|
||||
if (type_inst->opcode() == SpvOpTypeInt) {
|
||||
if (type_inst->opcode() == spv::Op::OpTypeInt) {
|
||||
return type_inst->GetSingleWordInOperand(0) == 32;
|
||||
}
|
||||
// Support booleans.
|
||||
if (type_inst->opcode() == SpvOpTypeBool) {
|
||||
if (type_inst->opcode() == spv::Op::OpTypeBool) {
|
||||
return true;
|
||||
}
|
||||
// Nothing else yet.
|
||||
@@ -699,7 +700,7 @@ bool InstructionFolder::IsFoldableType(Instruction* type_inst) const {
|
||||
bool InstructionFolder::FoldInstruction(Instruction* inst) const {
|
||||
bool modified = false;
|
||||
Instruction* folded_inst(inst);
|
||||
while (folded_inst->opcode() != SpvOpCopyObject &&
|
||||
while (folded_inst->opcode() != spv::Op::OpCopyObject &&
|
||||
FoldInstructionInternal(&*folded_inst)) {
|
||||
modified = true;
|
||||
}
|
||||
|
||||
14
3rdparty/spirv-tools/source/opt/fold.h
vendored
14
3rdparty/spirv-tools/source/opt/fold.h
vendored
@@ -55,7 +55,7 @@ class InstructionFolder {
|
||||
// IsFoldableOpcode test. If any error occurs during folding, the folder will
|
||||
// fail with a call to assert.
|
||||
uint32_t FoldScalars(
|
||||
SpvOp opcode,
|
||||
spv::Op opcode,
|
||||
const std::vector<const analysis::Constant*>& operands) const;
|
||||
|
||||
// Returns the result of performing an operation with the given |opcode| over
|
||||
@@ -72,12 +72,12 @@ class InstructionFolder {
|
||||
// IsFoldableOpcode test. If any error occurs during folding, the folder will
|
||||
// fail with a call to assert.
|
||||
std::vector<uint32_t> FoldVectors(
|
||||
SpvOp opcode, uint32_t num_dims,
|
||||
spv::Op opcode, uint32_t num_dims,
|
||||
const std::vector<const analysis::Constant*>& operands) const;
|
||||
|
||||
// Returns true if |opcode| represents an operation handled by FoldScalars or
|
||||
// FoldVectors.
|
||||
bool IsFoldableOpcode(SpvOp opcode) const;
|
||||
bool IsFoldableOpcode(spv::Op opcode) const;
|
||||
|
||||
// Returns true if |cst| is supported by FoldScalars and FoldVectors.
|
||||
bool IsFoldableConstant(const analysis::Constant* cst) const;
|
||||
@@ -126,22 +126,22 @@ class InstructionFolder {
|
||||
|
||||
// Returns the single-word result from performing the given unary operation on
|
||||
// the operand value which is passed in as a 32-bit word.
|
||||
uint32_t UnaryOperate(SpvOp opcode, uint32_t operand) const;
|
||||
uint32_t UnaryOperate(spv::Op opcode, uint32_t operand) const;
|
||||
|
||||
// Returns the single-word result from performing the given binary operation
|
||||
// on the operand values which are passed in as two 32-bit word.
|
||||
uint32_t BinaryOperate(SpvOp opcode, uint32_t a, uint32_t b) const;
|
||||
uint32_t BinaryOperate(spv::Op opcode, uint32_t a, uint32_t b) const;
|
||||
|
||||
// Returns the single-word result from performing the given ternary operation
|
||||
// on the operand values which are passed in as three 32-bit word.
|
||||
uint32_t TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b,
|
||||
uint32_t TernaryOperate(spv::Op opcode, uint32_t a, uint32_t b,
|
||||
uint32_t c) const;
|
||||
|
||||
// Returns the single-word result from performing the given operation on the
|
||||
// operand words. This only works with 32-bit operations and uses boolean
|
||||
// convention that 0u is false, and anything else is boolean true.
|
||||
// TODO(qining): Support operands other than 32-bit wide.
|
||||
uint32_t OperateWords(SpvOp opcode,
|
||||
uint32_t OperateWords(spv::Op opcode,
|
||||
const std::vector<uint32_t>& operand_words) const;
|
||||
|
||||
bool FoldInstructionInternal(Instruction* inst) const;
|
||||
|
||||
@@ -66,14 +66,14 @@ Pass::Status FoldSpecConstantOpAndCompositePass::Process() {
|
||||
if (const_mgr->GetType(inst) &&
|
||||
!const_mgr->GetType(inst)->decoration_empty())
|
||||
continue;
|
||||
switch (SpvOp opcode = inst->opcode()) {
|
||||
switch (spv::Op opcode = inst->opcode()) {
|
||||
// Records the values of Normal Constants.
|
||||
case SpvOp::SpvOpConstantTrue:
|
||||
case SpvOp::SpvOpConstantFalse:
|
||||
case SpvOp::SpvOpConstant:
|
||||
case SpvOp::SpvOpConstantNull:
|
||||
case SpvOp::SpvOpConstantComposite:
|
||||
case SpvOp::SpvOpSpecConstantComposite: {
|
||||
case spv::Op::OpConstantTrue:
|
||||
case spv::Op::OpConstantFalse:
|
||||
case spv::Op::OpConstant:
|
||||
case spv::Op::OpConstantNull:
|
||||
case spv::Op::OpConstantComposite:
|
||||
case spv::Op::OpSpecConstantComposite: {
|
||||
// A Constant instance will be created if the given instruction is a
|
||||
// Normal Constant whose value(s) are fixed. Note that for a composite
|
||||
// Spec Constant defined with OpSpecConstantComposite instruction, if
|
||||
@@ -84,8 +84,8 @@ Pass::Status FoldSpecConstantOpAndCompositePass::Process() {
|
||||
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);
|
||||
if (opcode == spv::Op::OpSpecConstantComposite) {
|
||||
inst->SetOpcode(spv::Op::OpConstantComposite);
|
||||
modified = true;
|
||||
}
|
||||
const_mgr->MapConstantToInst(const_value, inst);
|
||||
@@ -99,7 +99,7 @@ Pass::Status FoldSpecConstantOpAndCompositePass::Process() {
|
||||
// Constants will be added to id_to_const_val_ and const_val_to_id_ so
|
||||
// that we can use the new Normal Constants when folding following Spec
|
||||
// Constants.
|
||||
case SpvOp::SpvOpSpecConstantOp:
|
||||
case spv::Op::OpSpecConstantOp:
|
||||
modified |= ProcessOpSpecConstantOp(&inst_iter);
|
||||
break;
|
||||
default:
|
||||
@@ -118,11 +118,11 @@ bool FoldSpecConstantOpAndCompositePass::ProcessOpSpecConstantOp(
|
||||
"The first in-operand of OpSpecConstantOp instruction must be of "
|
||||
"SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER type");
|
||||
|
||||
switch (static_cast<SpvOp>(inst->GetSingleWordInOperand(0))) {
|
||||
case SpvOp::SpvOpCompositeExtract:
|
||||
case SpvOp::SpvOpVectorShuffle:
|
||||
case SpvOp::SpvOpCompositeInsert:
|
||||
case SpvOp::SpvOpQuantizeToF16:
|
||||
switch (static_cast<spv::Op>(inst->GetSingleWordInOperand(0))) {
|
||||
case spv::Op::OpCompositeExtract:
|
||||
case spv::Op::OpVectorShuffle:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
case spv::Op::OpQuantizeToF16:
|
||||
folded_inst = FoldWithInstructionFolder(pos);
|
||||
break;
|
||||
default:
|
||||
@@ -165,7 +165,7 @@ Instruction* FoldSpecConstantOpAndCompositePass::FoldWithInstructionFolder(
|
||||
// instruction and pass it to the instruction folder.
|
||||
std::unique_ptr<Instruction> inst((*inst_iter_ptr)->Clone(context()));
|
||||
inst->SetOpcode(
|
||||
static_cast<SpvOp>((*inst_iter_ptr)->GetSingleWordInOperand(0)));
|
||||
static_cast<spv::Op>((*inst_iter_ptr)->GetSingleWordInOperand(0)));
|
||||
inst->RemoveOperand(2);
|
||||
|
||||
// We want the current instruction to be replaced by an |OpConstant*|
|
||||
@@ -289,7 +289,7 @@ Instruction* FoldSpecConstantOpAndCompositePass::DoComponentWiseOperation(
|
||||
const Instruction* inst = &**pos;
|
||||
analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
|
||||
const analysis::Type* result_type = const_mgr->GetType(inst);
|
||||
SpvOp spec_opcode = static_cast<SpvOp>(inst->GetSingleWordInOperand(0));
|
||||
spv::Op spec_opcode = static_cast<spv::Op>(inst->GetSingleWordInOperand(0));
|
||||
// Check and collect operands.
|
||||
std::vector<const analysis::Constant*> operands;
|
||||
|
||||
|
||||
637
3rdparty/spirv-tools/source/opt/folding_rules.cpp
vendored
637
3rdparty/spirv-tools/source/opt/folding_rules.cpp
vendored
File diff suppressed because it is too large
Load Diff
10
3rdparty/spirv-tools/source/opt/folding_rules.h
vendored
10
3rdparty/spirv-tools/source/opt/folding_rules.h
vendored
@@ -64,7 +64,7 @@ class FoldingRules {
|
||||
virtual ~FoldingRules() = default;
|
||||
|
||||
const FoldingRuleSet& GetRulesForInstruction(Instruction* inst) const {
|
||||
if (inst->opcode() != SpvOpExtInst) {
|
||||
if (inst->opcode() != spv::Op::OpExtInst) {
|
||||
auto it = rules_.find(inst->opcode());
|
||||
if (it != rules_.end()) {
|
||||
return it->second;
|
||||
@@ -86,8 +86,14 @@ class FoldingRules {
|
||||
virtual void AddFoldingRules();
|
||||
|
||||
protected:
|
||||
struct hasher {
|
||||
size_t operator()(const spv::Op& op) const noexcept {
|
||||
return std::hash<uint32_t>()(uint32_t(op));
|
||||
}
|
||||
};
|
||||
|
||||
// The folding rules for core instructions.
|
||||
std::unordered_map<uint32_t, FoldingRuleSet> rules_;
|
||||
std::unordered_map<spv::Op, FoldingRuleSet, hasher> rules_;
|
||||
|
||||
// The folding rules for extended instructions.
|
||||
struct Key {
|
||||
|
||||
@@ -23,21 +23,21 @@ Pass::Status FreezeSpecConstantValuePass::Process() {
|
||||
auto ctx = context();
|
||||
ctx->module()->ForEachInst([&modified, ctx](Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOp::SpvOpSpecConstant:
|
||||
inst->SetOpcode(SpvOp::SpvOpConstant);
|
||||
case spv::Op::OpSpecConstant:
|
||||
inst->SetOpcode(spv::Op::OpConstant);
|
||||
modified = true;
|
||||
break;
|
||||
case SpvOp::SpvOpSpecConstantTrue:
|
||||
inst->SetOpcode(SpvOp::SpvOpConstantTrue);
|
||||
case spv::Op::OpSpecConstantTrue:
|
||||
inst->SetOpcode(spv::Op::OpConstantTrue);
|
||||
modified = true;
|
||||
break;
|
||||
case SpvOp::SpvOpSpecConstantFalse:
|
||||
inst->SetOpcode(SpvOp::SpvOpConstantFalse);
|
||||
case spv::Op::OpSpecConstantFalse:
|
||||
inst->SetOpcode(spv::Op::OpConstantFalse);
|
||||
modified = true;
|
||||
break;
|
||||
case SpvOp::SpvOpDecorate:
|
||||
if (inst->GetSingleWordInOperand(1) ==
|
||||
SpvDecoration::SpvDecorationSpecId) {
|
||||
case spv::Op::OpDecorate:
|
||||
if (spv::Decoration(inst->GetSingleWordInOperand(1)) ==
|
||||
spv::Decoration::SpecId) {
|
||||
ctx->KillInst(inst);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
2
3rdparty/spirv-tools/source/opt/function.cpp
vendored
2
3rdparty/spirv-tools/source/opt/function.cpp
vendored
@@ -264,7 +264,7 @@ std::string Function::PrettyPrint(uint32_t options) const {
|
||||
std::ostringstream str;
|
||||
ForEachInst([&str, options](const Instruction* inst) {
|
||||
str << inst->PrettyPrint(options);
|
||||
if (inst->opcode() != SpvOpFunctionEnd) {
|
||||
if (inst->opcode() != spv::Op::OpFunctionEnd) {
|
||||
str << std::endl;
|
||||
}
|
||||
});
|
||||
|
||||
2
3rdparty/spirv-tools/source/opt/function.h
vendored
2
3rdparty/spirv-tools/source/opt/function.h
vendored
@@ -253,7 +253,7 @@ inline void Function::RemoveEmptyBlocks() {
|
||||
auto first_empty =
|
||||
std::remove_if(std::begin(blocks_), std::end(blocks_),
|
||||
[](const std::unique_ptr<BasicBlock>& bb) -> bool {
|
||||
return bb->GetLabelInst()->opcode() == SpvOpNop;
|
||||
return bb->GetLabelInst()->opcode() == spv::Op::OpNop;
|
||||
});
|
||||
blocks_.erase(first_empty, std::end(blocks_));
|
||||
}
|
||||
|
||||
@@ -158,7 +158,6 @@
|
||||
#include "source/util/make_unique.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/unified1/GLSL.std.450.h"
|
||||
#include "spirv/unified1/spirv.h"
|
||||
#include "type_manager.h"
|
||||
#include "types.h"
|
||||
|
||||
@@ -194,14 +193,15 @@ spvtools::DiagnosticStream GraphicsRobustAccessPass::Fail() {
|
||||
|
||||
spv_result_t GraphicsRobustAccessPass::IsCompatibleModule() {
|
||||
auto* feature_mgr = context()->get_feature_mgr();
|
||||
if (!feature_mgr->HasCapability(SpvCapabilityShader))
|
||||
if (!feature_mgr->HasCapability(spv::Capability::Shader))
|
||||
return Fail() << "Can only process Shader modules";
|
||||
if (feature_mgr->HasCapability(SpvCapabilityVariablePointers))
|
||||
if (feature_mgr->HasCapability(spv::Capability::VariablePointers))
|
||||
return Fail() << "Can't process modules with VariablePointers capability";
|
||||
if (feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer))
|
||||
if (feature_mgr->HasCapability(
|
||||
spv::Capability::VariablePointersStorageBuffer))
|
||||
return Fail() << "Can't process modules with VariablePointersStorageBuffer "
|
||||
"capability";
|
||||
if (feature_mgr->HasCapability(SpvCapabilityRuntimeDescriptorArrayEXT)) {
|
||||
if (feature_mgr->HasCapability(spv::Capability::RuntimeDescriptorArrayEXT)) {
|
||||
// These have a RuntimeArray outside of Block-decorated struct. There
|
||||
// is no way to compute the array length from within SPIR-V.
|
||||
return Fail() << "Can't process modules with RuntimeDescriptorArrayEXT "
|
||||
@@ -210,8 +210,9 @@ spv_result_t GraphicsRobustAccessPass::IsCompatibleModule() {
|
||||
|
||||
{
|
||||
auto* inst = context()->module()->GetMemoryModel();
|
||||
const auto addressing_model = inst->GetSingleWordOperand(0);
|
||||
if (addressing_model != SpvAddressingModelLogical)
|
||||
const auto addressing_model =
|
||||
spv::AddressingModel(inst->GetSingleWordOperand(0));
|
||||
if (addressing_model != spv::AddressingModel::Logical)
|
||||
return Fail() << "Addressing model must be Logical. Found "
|
||||
<< inst->PrettyPrint();
|
||||
}
|
||||
@@ -237,11 +238,11 @@ bool GraphicsRobustAccessPass::ProcessAFunction(opt::Function* function) {
|
||||
for (auto& block : *function) {
|
||||
for (auto& inst : block) {
|
||||
switch (inst.opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
access_chains.push_back(&inst);
|
||||
break;
|
||||
case SpvOpImageTexelPointer:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
image_texel_pointers.push_back(&inst);
|
||||
break;
|
||||
default:
|
||||
@@ -268,7 +269,7 @@ void GraphicsRobustAccessPass::ClampIndicesForAccessChain(
|
||||
auto* def_use_mgr = context()->get_def_use_mgr();
|
||||
auto* type_mgr = context()->get_type_mgr();
|
||||
const bool have_int64_cap =
|
||||
context()->get_feature_mgr()->HasCapability(SpvCapabilityInt64);
|
||||
context()->get_feature_mgr()->HasCapability(spv::Capability::Int64);
|
||||
|
||||
// Replaces one of the OpAccessChain index operands with a new value.
|
||||
// Updates def-use analysis.
|
||||
@@ -451,7 +452,7 @@ void GraphicsRobustAccessPass::ClampIndicesForAccessChain(
|
||||
// It doesn't matter if 1 is signed or unsigned.
|
||||
auto* one = GetValueForType(1, wider_type);
|
||||
auto* count_minus_1 = InsertInst(
|
||||
&inst, SpvOpISub, type_mgr->GetId(wider_type), TakeNextId(),
|
||||
&inst, spv::Op::OpISub, type_mgr->GetId(wider_type), TakeNextId(),
|
||||
{{SPV_OPERAND_TYPE_ID, {count_inst->result_id()}},
|
||||
{SPV_OPERAND_TYPE_ID, {one->result_id()}}});
|
||||
auto* zero = GetValueForType(0, wider_type);
|
||||
@@ -486,15 +487,15 @@ void GraphicsRobustAccessPass::ClampIndicesForAccessChain(
|
||||
Instruction* index_inst = GetDef(index_id);
|
||||
|
||||
switch (pointee_type->opcode()) {
|
||||
case SpvOpTypeMatrix: // Use column count
|
||||
case SpvOpTypeVector: // Use component count
|
||||
case spv::Op::OpTypeMatrix: // Use column count
|
||||
case spv::Op::OpTypeVector: // Use component count
|
||||
{
|
||||
const uint32_t count = pointee_type->GetSingleWordOperand(2);
|
||||
clamp_to_literal_count(idx, count);
|
||||
pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
|
||||
} break;
|
||||
|
||||
case SpvOpTypeArray: {
|
||||
case spv::Op::OpTypeArray: {
|
||||
// The array length can be a spec constant, so go through the general
|
||||
// case.
|
||||
Instruction* array_len = GetDef(pointee_type->GetSingleWordOperand(2));
|
||||
@@ -502,11 +503,11 @@ void GraphicsRobustAccessPass::ClampIndicesForAccessChain(
|
||||
pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
|
||||
} break;
|
||||
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
// SPIR-V requires the index to be an OpConstant.
|
||||
// We need to know the index literal value so we can compute the next
|
||||
// pointee type.
|
||||
if (index_inst->opcode() != SpvOpConstant ||
|
||||
if (index_inst->opcode() != spv::Op::OpConstant ||
|
||||
!constant_mgr->GetConstantFromInst(index_inst)
|
||||
->type()
|
||||
->AsInteger()) {
|
||||
@@ -537,7 +538,7 @@ void GraphicsRobustAccessPass::ClampIndicesForAccessChain(
|
||||
// No need to clamp this index. We just checked that it's valid.
|
||||
} break;
|
||||
|
||||
case SpvOpTypeRuntimeArray: {
|
||||
case spv::Op::OpTypeRuntimeArray: {
|
||||
auto* array_len = MakeRuntimeArrayLengthInst(&inst, idx);
|
||||
if (!array_len) { // We've already signaled an error.
|
||||
return;
|
||||
@@ -571,7 +572,7 @@ uint32_t GraphicsRobustAccessPass::GetGlslInsts() {
|
||||
module_status_.glsl_insts_id = TakeNextId();
|
||||
std::vector<uint32_t> words = spvtools::utils::MakeVector(glsl);
|
||||
auto import_inst = MakeUnique<Instruction>(
|
||||
context(), SpvOpExtInstImport, 0, module_status_.glsl_insts_id,
|
||||
context(), spv::Op::OpExtInstImport, 0, module_status_.glsl_insts_id,
|
||||
std::initializer_list<Operand>{
|
||||
Operand{SPV_OPERAND_TYPE_LITERAL_STRING, std::move(words)}});
|
||||
Instruction* inst = import_inst.get();
|
||||
@@ -609,8 +610,8 @@ opt::Instruction* opt::GraphicsRobustAccessPass::WidenInteger(
|
||||
auto type_id = context()->get_type_mgr()->GetId(unsigned_type);
|
||||
auto conversion_id = TakeNextId();
|
||||
auto* conversion = InsertInst(
|
||||
before_inst, (sign_extend ? SpvOpSConvert : SpvOpUConvert), type_id,
|
||||
conversion_id, {{SPV_OPERAND_TYPE_ID, {value->result_id()}}});
|
||||
before_inst, (sign_extend ? spv::Op::OpSConvert : spv::Op::OpUConvert),
|
||||
type_id, conversion_id, {{SPV_OPERAND_TYPE_ID, {value->result_id()}}});
|
||||
return conversion;
|
||||
}
|
||||
|
||||
@@ -628,7 +629,7 @@ Instruction* GraphicsRobustAccessPass::MakeUMinInst(
|
||||
(void)xwidth;
|
||||
(void)ywidth;
|
||||
auto* smin_inst = InsertInst(
|
||||
where, SpvOpExtInst, x->type_id(), smin_id,
|
||||
where, spv::Op::OpExtInst, x->type_id(), smin_id,
|
||||
{
|
||||
{SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
|
||||
{SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450UMin}},
|
||||
@@ -655,7 +656,7 @@ Instruction* GraphicsRobustAccessPass::MakeSClampInst(
|
||||
(void)minwidth;
|
||||
(void)maxwidth;
|
||||
auto* clamp_inst = InsertInst(
|
||||
where, SpvOpExtInst, x->type_id(), clamp_id,
|
||||
where, spv::Op::OpExtInst, x->type_id(), clamp_id,
|
||||
{
|
||||
{SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
|
||||
{SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450SClamp}},
|
||||
@@ -689,13 +690,13 @@ Instruction* GraphicsRobustAccessPass::MakeRuntimeArrayLengthInst(
|
||||
Instruction* pointer_to_containing_struct = nullptr;
|
||||
while (steps_remaining > 0) {
|
||||
switch (current_access_chain->opcode()) {
|
||||
case SpvOpCopyObject:
|
||||
case spv::Op::OpCopyObject:
|
||||
// Whoops. Walk right through this one.
|
||||
current_access_chain =
|
||||
GetDef(current_access_chain->GetSingleWordInOperand(0));
|
||||
break;
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain: {
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain: {
|
||||
const int first_index_operand = 3;
|
||||
// How many indices in this access chain contribute to getting us
|
||||
// to an element in the runtime array?
|
||||
@@ -793,7 +794,8 @@ Instruction* GraphicsRobustAccessPass::MakeRuntimeArrayLengthInst(
|
||||
analysis::Integer uint_type_for_query(32, false);
|
||||
auto* uint_type = type_mgr->GetRegisteredType(&uint_type_for_query);
|
||||
auto* array_len = InsertInst(
|
||||
access_chain, SpvOpArrayLength, type_mgr->GetId(uint_type), array_len_id,
|
||||
access_chain, spv::Op::OpArrayLength, type_mgr->GetId(uint_type),
|
||||
array_len_id,
|
||||
{{SPV_OPERAND_TYPE_ID, {pointer_to_containing_struct->result_id()}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index_of_runtime_array}}});
|
||||
return array_len;
|
||||
@@ -839,11 +841,11 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
|
||||
// Declare the ImageQuery capability if the module doesn't already have it.
|
||||
auto* feature_mgr = context()->get_feature_mgr();
|
||||
if (!feature_mgr->HasCapability(SpvCapabilityImageQuery)) {
|
||||
if (!feature_mgr->HasCapability(spv::Capability::ImageQuery)) {
|
||||
auto cap = MakeUnique<Instruction>(
|
||||
context(), SpvOpCapability, 0, 0,
|
||||
context(), spv::Op::OpCapability, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}});
|
||||
{SPV_OPERAND_TYPE_CAPABILITY, {spv::Capability::ImageQuery}}});
|
||||
def_use_mgr->AnalyzeInstDefUse(cap.get());
|
||||
context()->AddCapability(std::move(cap));
|
||||
feature_mgr->Analyze(context()->module());
|
||||
@@ -890,21 +892,21 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
const int arrayness_bonus = arrayed ? 1 : 0;
|
||||
int num_coords = 0;
|
||||
switch (dim) {
|
||||
case SpvDimBuffer:
|
||||
case spv::Dim::Buffer:
|
||||
case SpvDim1D:
|
||||
num_coords = 1;
|
||||
break;
|
||||
case SpvDimCube:
|
||||
case spv::Dim::Cube:
|
||||
// For cube, we need bounds for x, y, but not face.
|
||||
case SpvDimRect:
|
||||
case spv::Dim::Rect:
|
||||
case SpvDim2D:
|
||||
num_coords = 2;
|
||||
break;
|
||||
case SpvDim3D:
|
||||
num_coords = 3;
|
||||
break;
|
||||
case SpvDimSubpassData:
|
||||
case SpvDimMax:
|
||||
case spv::Dim::SubpassData:
|
||||
case spv::Dim::Max:
|
||||
return Fail() << "Invalid image dimension for OpImageTexelPointer: "
|
||||
<< int(dim);
|
||||
break;
|
||||
@@ -941,12 +943,12 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
|
||||
const uint32_t image_id = TakeNextId();
|
||||
auto* image =
|
||||
InsertInst(image_texel_pointer, SpvOpLoad, image_type_id, image_id,
|
||||
InsertInst(image_texel_pointer, spv::Op::OpLoad, image_type_id, image_id,
|
||||
{{SPV_OPERAND_TYPE_ID, {image_ptr->result_id()}}});
|
||||
|
||||
const uint32_t query_size_id = TakeNextId();
|
||||
auto* query_size =
|
||||
InsertInst(image_texel_pointer, SpvOpImageQuerySize,
|
||||
InsertInst(image_texel_pointer, spv::Op::OpImageQuerySize,
|
||||
type_mgr->GetTypeInstruction(query_size_type), query_size_id,
|
||||
{{SPV_OPERAND_TYPE_ID, {image->result_id()}}});
|
||||
|
||||
@@ -962,7 +964,7 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
// in the face index ranging from 0 through 5. The inclusive upper bound
|
||||
// on the third coordinate therefore is multiplied by 6.
|
||||
auto* query_size_including_faces = query_size;
|
||||
if (arrayed && (dim == SpvDimCube)) {
|
||||
if (arrayed && (dim == spv::Dim::Cube)) {
|
||||
// Multiply the last coordinate by 6.
|
||||
auto* component_6 = constant_mgr->GetConstant(coord_component_type, {6});
|
||||
const uint32_t component_6_id =
|
||||
@@ -974,7 +976,7 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
constant_mgr->GetDefiningInstruction(multiplicand);
|
||||
const auto query_size_including_faces_id = TakeNextId();
|
||||
query_size_including_faces = InsertInst(
|
||||
image_texel_pointer, SpvOpIMul,
|
||||
image_texel_pointer, spv::Op::OpIMul,
|
||||
type_mgr->GetTypeInstruction(query_size_type),
|
||||
query_size_including_faces_id,
|
||||
{{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
|
||||
@@ -998,7 +1000,7 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
|
||||
const uint32_t query_max_including_faces_id = TakeNextId();
|
||||
auto* query_max_including_faces = InsertInst(
|
||||
image_texel_pointer, SpvOpISub,
|
||||
image_texel_pointer, spv::Op::OpISub,
|
||||
type_mgr->GetTypeInstruction(query_size_type),
|
||||
query_max_including_faces_id,
|
||||
{{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
|
||||
@@ -1016,12 +1018,12 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
// Get the sample count via OpImageQuerySamples
|
||||
const auto query_samples_id = TakeNextId();
|
||||
auto* query_samples = InsertInst(
|
||||
image_texel_pointer, SpvOpImageQuerySamples,
|
||||
image_texel_pointer, spv::Op::OpImageQuerySamples,
|
||||
constant_mgr->GetDefiningInstruction(component_0)->type_id(),
|
||||
query_samples_id, {{SPV_OPERAND_TYPE_ID, {image->result_id()}}});
|
||||
|
||||
const auto max_samples_id = TakeNextId();
|
||||
auto* max_samples = InsertInst(image_texel_pointer, SpvOpImageQuerySamples,
|
||||
auto* max_samples = InsertInst(image_texel_pointer, spv::Op::OpImageQuerySamples,
|
||||
query_samples->type_id(), max_samples_id,
|
||||
{{SPV_OPERAND_TYPE_ID, {query_samples_id}},
|
||||
{SPV_OPERAND_TYPE_ID, {component_1_id}}});
|
||||
@@ -1043,7 +1045,7 @@ spv_result_t GraphicsRobustAccessPass::ClampCoordinateForImageTexelPointer(
|
||||
}
|
||||
|
||||
opt::Instruction* GraphicsRobustAccessPass::InsertInst(
|
||||
opt::Instruction* where_inst, SpvOp opcode, uint32_t type_id,
|
||||
opt::Instruction* where_inst, spv::Op opcode, uint32_t type_id,
|
||||
uint32_t result_id, const Instruction::OperandList& operands) {
|
||||
module_status_.modified = true;
|
||||
auto* result = where_inst->InsertBefore(
|
||||
|
||||
@@ -133,7 +133,7 @@ class GraphicsRobustAccessPass : public Pass {
|
||||
// Returns a new instruction inserted before |where_inst|, and created from
|
||||
// the remaining arguments. Registers the definitions and uses of the new
|
||||
// instruction and also records its block.
|
||||
opt::Instruction* InsertInst(opt::Instruction* where_inst, SpvOp opcode,
|
||||
opt::Instruction* InsertInst(opt::Instruction* where_inst, spv::Op opcode,
|
||||
uint32_t type_id, uint32_t result_id,
|
||||
const Instruction::OperandList& operands);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
Pass::Status IfConversion::Process() {
|
||||
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
|
||||
return Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ Pass::Status IfConversion::Process() {
|
||||
|
||||
// Get an insertion point.
|
||||
auto iter = block.begin();
|
||||
while (iter != block.end() && iter->opcode() == SpvOpPhi) {
|
||||
while (iter != block.end() && iter->opcode() == spv::Op::OpPhi) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
@@ -171,23 +171,26 @@ bool IfConversion::CheckBlock(BasicBlock* block, DominatorAnalysis* dominators,
|
||||
*common = dominators->CommonDominator(inc0, inc1);
|
||||
if (!*common || cfg()->IsPseudoEntryBlock(*common)) return false;
|
||||
Instruction* branch = (*common)->terminator();
|
||||
if (branch->opcode() != SpvOpBranchConditional) return false;
|
||||
if (branch->opcode() != spv::Op::OpBranchConditional) return false;
|
||||
auto merge = (*common)->GetMergeInst();
|
||||
if (!merge || merge->opcode() != SpvOpSelectionMerge) return false;
|
||||
if (merge->GetSingleWordInOperand(1) == SpvSelectionControlDontFlattenMask)
|
||||
if (!merge || merge->opcode() != spv::Op::OpSelectionMerge) return false;
|
||||
if (spv::SelectionControlMask(merge->GetSingleWordInOperand(1)) ==
|
||||
spv::SelectionControlMask::DontFlatten) {
|
||||
return false;
|
||||
}
|
||||
if ((*common)->MergeBlockIdIfAny() != block->id()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IfConversion::CheckPhiUsers(Instruction* phi, BasicBlock* block) {
|
||||
return get_def_use_mgr()->WhileEachUser(phi, [block,
|
||||
this](Instruction* user) {
|
||||
if (user->opcode() == SpvOpPhi && context()->get_instr_block(user) == block)
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
return get_def_use_mgr()->WhileEachUser(
|
||||
phi, [block, this](Instruction* user) {
|
||||
if (user->opcode() == spv::Op::OpPhi &&
|
||||
context()->get_instr_block(user) == block)
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t IfConversion::SplatCondition(analysis::Vector* vec_data_ty,
|
||||
@@ -207,9 +210,9 @@ uint32_t IfConversion::SplatCondition(analysis::Vector* vec_data_ty,
|
||||
|
||||
bool IfConversion::CheckType(uint32_t id) {
|
||||
Instruction* type = get_def_use_mgr()->GetDef(id);
|
||||
SpvOp op = type->opcode();
|
||||
if (spvOpcodeIsScalarType(op) || op == SpvOpTypePointer ||
|
||||
op == SpvOpTypeVector)
|
||||
spv::Op op = type->opcode();
|
||||
if (spvOpcodeIsScalarType(op) || op == spv::Op::OpTypePointer ||
|
||||
op == spv::Op::OpTypeVector)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -255,7 +258,7 @@ void IfConversion::HoistInstruction(Instruction* inst, BasicBlock* target_block,
|
||||
});
|
||||
|
||||
Instruction* insertion_pos = target_block->terminator();
|
||||
if ((insertion_pos)->PreviousNode()->opcode() == SpvOpSelectionMerge) {
|
||||
if ((insertion_pos)->PreviousNode()->opcode() == spv::Op::OpSelectionMerge) {
|
||||
insertion_pos = insertion_pos->PreviousNode();
|
||||
}
|
||||
inst->RemoveFromList();
|
||||
|
||||
@@ -21,26 +21,24 @@
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
|
||||
const uint32_t kTypePointerTypeIdInIdx = 1;
|
||||
|
||||
} // anonymous namespace
|
||||
constexpr uint32_t kTypePointerTypeIdInIdx = 1;
|
||||
} // namespace
|
||||
|
||||
bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) {
|
||||
const Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
|
||||
switch (typeInst->opcode()) {
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampledImage:
|
||||
case spv::Op::OpTypeSampler:
|
||||
case spv::Op::OpTypeImage:
|
||||
case spv::Op::OpTypeSampledImage:
|
||||
return true;
|
||||
case SpvOpTypePointer:
|
||||
case spv::Op::OpTypePointer:
|
||||
return IsOpaqueType(
|
||||
typeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// TODO(greg-lunarg): Handle arrays containing opaque type
|
||||
if (typeInst->opcode() != SpvOpTypeStruct) return false;
|
||||
if (typeInst->opcode() != spv::Op::OpTypeStruct) return false;
|
||||
// Return true if any member is opaque
|
||||
return !typeInst->WhileEachInId([this](const uint32_t* tid) {
|
||||
if (IsOpaqueType(*tid)) return false;
|
||||
|
||||
82
3rdparty/spirv-tools/source/opt/inline_pass.cpp
vendored
82
3rdparty/spirv-tools/source/opt/inline_pass.cpp
vendored
@@ -23,24 +23,24 @@
|
||||
#include "source/opt/reflect.h"
|
||||
#include "source/util/make_unique.h"
|
||||
|
||||
// Indices of operands in SPIR-V instructions
|
||||
|
||||
static const int kSpvFunctionCallFunctionId = 2;
|
||||
static const int kSpvFunctionCallArgumentId = 3;
|
||||
static const int kSpvReturnValueId = 0;
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
// Indices of operands in SPIR-V instructions
|
||||
constexpr int kSpvFunctionCallFunctionId = 2;
|
||||
constexpr int kSpvFunctionCallArgumentId = 3;
|
||||
constexpr int kSpvReturnValueId = 0;
|
||||
} // namespace
|
||||
|
||||
uint32_t InlinePass::AddPointerToType(uint32_t type_id,
|
||||
SpvStorageClass storage_class) {
|
||||
spv::StorageClass storage_class) {
|
||||
uint32_t resultId = context()->TakeNextId();
|
||||
if (resultId == 0) {
|
||||
return resultId;
|
||||
}
|
||||
|
||||
std::unique_ptr<Instruction> type_inst(
|
||||
new Instruction(context(), SpvOpTypePointer, 0, resultId,
|
||||
new Instruction(context(), spv::Op::OpTypePointer, 0, resultId,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
{uint32_t(storage_class)}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_id}}}));
|
||||
@@ -48,8 +48,8 @@ uint32_t InlinePass::AddPointerToType(uint32_t type_id,
|
||||
analysis::Type* pointeeTy;
|
||||
std::unique_ptr<analysis::Pointer> pointerTy;
|
||||
std::tie(pointeeTy, pointerTy) =
|
||||
context()->get_type_mgr()->GetTypeAndPointerType(type_id,
|
||||
SpvStorageClassFunction);
|
||||
context()->get_type_mgr()->GetTypeAndPointerType(
|
||||
type_id, spv::StorageClass::Function);
|
||||
context()->get_type_mgr()->RegisterType(resultId, *pointerTy);
|
||||
return resultId;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ uint32_t InlinePass::AddPointerToType(uint32_t type_id,
|
||||
void InlinePass::AddBranch(uint32_t label_id,
|
||||
std::unique_ptr<BasicBlock>* block_ptr) {
|
||||
std::unique_ptr<Instruction> newBranch(
|
||||
new Instruction(context(), SpvOpBranch, 0, 0,
|
||||
new Instruction(context(), spv::Op::OpBranch, 0, 0,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}}));
|
||||
(*block_ptr)->AddInstruction(std::move(newBranch));
|
||||
}
|
||||
@@ -66,7 +66,7 @@ void InlinePass::AddBranchCond(uint32_t cond_id, uint32_t true_id,
|
||||
uint32_t false_id,
|
||||
std::unique_ptr<BasicBlock>* block_ptr) {
|
||||
std::unique_ptr<Instruction> newBranch(
|
||||
new Instruction(context(), SpvOpBranchConditional, 0, 0,
|
||||
new Instruction(context(), spv::Op::OpBranchConditional, 0, 0,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {false_id}}}));
|
||||
@@ -76,7 +76,7 @@ void InlinePass::AddBranchCond(uint32_t cond_id, uint32_t true_id,
|
||||
void InlinePass::AddLoopMerge(uint32_t merge_id, uint32_t continue_id,
|
||||
std::unique_ptr<BasicBlock>* block_ptr) {
|
||||
std::unique_ptr<Instruction> newLoopMerge(new Instruction(
|
||||
context(), SpvOpLoopMerge, 0, 0,
|
||||
context(), spv::Op::OpLoopMerge, 0, 0,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {continue_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_LOOP_CONTROL, {0}}}));
|
||||
@@ -88,7 +88,7 @@ void InlinePass::AddStore(uint32_t ptr_id, uint32_t val_id,
|
||||
const Instruction* line_inst,
|
||||
const DebugScope& dbg_scope) {
|
||||
std::unique_ptr<Instruction> newStore(
|
||||
new Instruction(context(), SpvOpStore, 0, 0,
|
||||
new Instruction(context(), spv::Op::OpStore, 0, 0,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {val_id}}}));
|
||||
if (line_inst != nullptr) {
|
||||
@@ -103,7 +103,7 @@ void InlinePass::AddLoad(uint32_t type_id, uint32_t resultId, uint32_t ptr_id,
|
||||
const Instruction* line_inst,
|
||||
const DebugScope& dbg_scope) {
|
||||
std::unique_ptr<Instruction> newLoad(
|
||||
new Instruction(context(), SpvOpLoad, type_id, resultId,
|
||||
new Instruction(context(), spv::Op::OpLoad, type_id, resultId,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}}}));
|
||||
if (line_inst != nullptr) {
|
||||
newLoad->AddDebugLine(line_inst);
|
||||
@@ -114,27 +114,27 @@ void InlinePass::AddLoad(uint32_t type_id, uint32_t resultId, uint32_t ptr_id,
|
||||
|
||||
std::unique_ptr<Instruction> InlinePass::NewLabel(uint32_t label_id) {
|
||||
std::unique_ptr<Instruction> newLabel(
|
||||
new Instruction(context(), SpvOpLabel, 0, label_id, {}));
|
||||
new Instruction(context(), spv::Op::OpLabel, 0, label_id, {}));
|
||||
return newLabel;
|
||||
}
|
||||
|
||||
uint32_t InlinePass::GetFalseId() {
|
||||
if (false_id_ != 0) return false_id_;
|
||||
false_id_ = get_module()->GetGlobalValue(SpvOpConstantFalse);
|
||||
false_id_ = get_module()->GetGlobalValue(spv::Op::OpConstantFalse);
|
||||
if (false_id_ != 0) return false_id_;
|
||||
uint32_t boolId = get_module()->GetGlobalValue(SpvOpTypeBool);
|
||||
uint32_t boolId = get_module()->GetGlobalValue(spv::Op::OpTypeBool);
|
||||
if (boolId == 0) {
|
||||
boolId = context()->TakeNextId();
|
||||
if (boolId == 0) {
|
||||
return 0;
|
||||
}
|
||||
get_module()->AddGlobalValue(SpvOpTypeBool, boolId, 0);
|
||||
get_module()->AddGlobalValue(spv::Op::OpTypeBool, boolId, 0);
|
||||
}
|
||||
false_id_ = context()->TakeNextId();
|
||||
if (false_id_ == 0) {
|
||||
return 0;
|
||||
}
|
||||
get_module()->AddGlobalValue(SpvOpConstantFalse, false_id_, boolId);
|
||||
get_module()->AddGlobalValue(spv::Op::OpConstantFalse, false_id_, boolId);
|
||||
return false_id_;
|
||||
}
|
||||
|
||||
@@ -157,10 +157,10 @@ bool InlinePass::CloneAndMapLocals(
|
||||
analysis::DebugInlinedAtContext* inlined_at_ctx) {
|
||||
auto callee_block_itr = calleeFn->begin();
|
||||
auto callee_var_itr = callee_block_itr->begin();
|
||||
while (callee_var_itr->opcode() == SpvOp::SpvOpVariable ||
|
||||
while (callee_var_itr->opcode() == spv::Op::OpVariable ||
|
||||
callee_var_itr->GetCommonDebugOpcode() ==
|
||||
CommonDebugInfoDebugDeclare) {
|
||||
if (callee_var_itr->opcode() != SpvOp::SpvOpVariable) {
|
||||
if (callee_var_itr->opcode() != spv::Op::OpVariable) {
|
||||
++callee_var_itr;
|
||||
continue;
|
||||
}
|
||||
@@ -191,10 +191,11 @@ uint32_t InlinePass::CreateReturnVar(
|
||||
"Cannot create a return variable of type void.");
|
||||
// Find or create ptr to callee return type.
|
||||
uint32_t returnVarTypeId =
|
||||
type_mgr->FindPointerToType(calleeTypeId, SpvStorageClassFunction);
|
||||
type_mgr->FindPointerToType(calleeTypeId, spv::StorageClass::Function);
|
||||
|
||||
if (returnVarTypeId == 0) {
|
||||
returnVarTypeId = AddPointerToType(calleeTypeId, SpvStorageClassFunction);
|
||||
returnVarTypeId =
|
||||
AddPointerToType(calleeTypeId, spv::StorageClass::Function);
|
||||
if (returnVarTypeId == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -206,17 +207,18 @@ uint32_t InlinePass::CreateReturnVar(
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<Instruction> var_inst(
|
||||
new Instruction(context(), SpvOpVariable, returnVarTypeId, returnVarId,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
{SpvStorageClassFunction}}}));
|
||||
std::unique_ptr<Instruction> var_inst(new Instruction(
|
||||
context(), spv::Op::OpVariable, returnVarTypeId, returnVarId,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
{(uint32_t)spv::StorageClass::Function}}}));
|
||||
new_vars->push_back(std::move(var_inst));
|
||||
get_decoration_mgr()->CloneDecorations(calleeFn->result_id(), returnVarId);
|
||||
return returnVarId;
|
||||
}
|
||||
|
||||
bool InlinePass::IsSameBlockOp(const Instruction* inst) const {
|
||||
return inst->opcode() == SpvOpSampledImage || inst->opcode() == SpvOpImage;
|
||||
return inst->opcode() == spv::Op::OpSampledImage ||
|
||||
inst->opcode() == spv::Op::OpImage;
|
||||
}
|
||||
|
||||
bool InlinePass::CloneSameBlockOps(
|
||||
@@ -299,9 +301,9 @@ InstructionList::iterator InlinePass::AddStoresForVariableInitializers(
|
||||
std::unique_ptr<BasicBlock>* new_blk_ptr,
|
||||
UptrVectorIterator<BasicBlock> callee_first_block_itr) {
|
||||
auto callee_itr = callee_first_block_itr->begin();
|
||||
while (callee_itr->opcode() == SpvOp::SpvOpVariable ||
|
||||
while (callee_itr->opcode() == spv::Op::OpVariable ||
|
||||
callee_itr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) {
|
||||
if (callee_itr->opcode() == SpvOp::SpvOpVariable &&
|
||||
if (callee_itr->opcode() == spv::Op::OpVariable &&
|
||||
callee_itr->NumInOperands() == 2) {
|
||||
assert(callee2caller.count(callee_itr->result_id()) &&
|
||||
"Expected the variable to have already been mapped.");
|
||||
@@ -330,7 +332,8 @@ bool InlinePass::InlineSingleInstruction(
|
||||
BasicBlock* new_blk_ptr, const Instruction* inst, uint32_t dbg_inlined_at) {
|
||||
// If we have return, it must be at the end of the callee. We will handle
|
||||
// it at the end.
|
||||
if (inst->opcode() == SpvOpReturnValue || inst->opcode() == SpvOpReturn)
|
||||
if (inst->opcode() == spv::Op::OpReturnValue ||
|
||||
inst->opcode() == spv::Op::OpReturn)
|
||||
return true;
|
||||
|
||||
// Copy callee instruction and remap all input Ids.
|
||||
@@ -366,7 +369,7 @@ std::unique_ptr<BasicBlock> InlinePass::InlineReturn(
|
||||
analysis::DebugInlinedAtContext* inlined_at_ctx, Function* calleeFn,
|
||||
const Instruction* inst, uint32_t returnVarId) {
|
||||
// Store return value to return variable.
|
||||
if (inst->opcode() == SpvOpReturnValue) {
|
||||
if (inst->opcode() == spv::Op::OpReturnValue) {
|
||||
assert(returnVarId != 0);
|
||||
uint32_t valId = inst->GetInOperand(kSpvReturnValueId).words[0];
|
||||
const auto mapItr = callee2caller.find(valId);
|
||||
@@ -388,7 +391,8 @@ std::unique_ptr<BasicBlock> InlinePass::InlineReturn(
|
||||
}
|
||||
if (returnLabelId == 0) return new_blk_ptr;
|
||||
|
||||
if (inst->opcode() == SpvOpReturn || inst->opcode() == SpvOpReturnValue)
|
||||
if (inst->opcode() == spv::Op::OpReturn ||
|
||||
inst->opcode() == spv::Op::OpReturnValue)
|
||||
AddBranch(returnLabelId, &new_blk_ptr);
|
||||
new_blocks->push_back(std::move(new_blk_ptr));
|
||||
return MakeUnique<BasicBlock>(NewLabel(returnLabelId));
|
||||
@@ -499,7 +503,7 @@ void InlinePass::MoveLoopMergeInstToFirstBlock(
|
||||
// Insert a modified copy of the loop merge into the first block.
|
||||
auto loop_merge_itr = last->tail();
|
||||
--loop_merge_itr;
|
||||
assert(loop_merge_itr->opcode() == SpvOpLoopMerge);
|
||||
assert(loop_merge_itr->opcode() == spv::Op::OpLoopMerge);
|
||||
std::unique_ptr<Instruction> cp_inst(loop_merge_itr->Clone(context()));
|
||||
first->tail().InsertBefore(std::move(cp_inst));
|
||||
|
||||
@@ -696,7 +700,7 @@ bool InlinePass::GenInlineCode(
|
||||
}
|
||||
|
||||
bool InlinePass::IsInlinableFunctionCall(const Instruction* inst) {
|
||||
if (inst->opcode() != SpvOp::SpvOpFunctionCall) return false;
|
||||
if (inst->opcode() != spv::Op::OpFunctionCall) return false;
|
||||
const uint32_t calleeFnId =
|
||||
inst->GetSingleWordOperand(kSpvFunctionCallFunctionId);
|
||||
const auto ci = inlinable_.find(calleeFnId);
|
||||
@@ -738,7 +742,7 @@ void InlinePass::UpdateSucceedingPhis(
|
||||
bool InlinePass::HasNoReturnInLoop(Function* func) {
|
||||
// If control not structured, do not do loop/return analysis
|
||||
// TODO: Analyze returns in non-structured control flow
|
||||
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
|
||||
if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return false;
|
||||
const auto structured_analysis = context()->GetStructuredCFGAnalysis();
|
||||
// Search for returns in structured construct.
|
||||
@@ -776,7 +780,7 @@ bool InlinePass::IsInlinableFunction(Function* func) {
|
||||
if (func->cbegin() == func->cend()) return false;
|
||||
|
||||
// Do not inline functions with DontInline flag.
|
||||
if (func->control_mask() & SpvFunctionControlDontInlineMask) {
|
||||
if (func->control_mask() & uint32_t(spv::FunctionControlMask::DontInline)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -811,7 +815,7 @@ bool InlinePass::IsInlinableFunction(Function* func) {
|
||||
|
||||
bool InlinePass::ContainsAbortOtherThanUnreachable(Function* func) const {
|
||||
return !func->WhileEachInst([](Instruction* inst) {
|
||||
return inst->opcode() == SpvOpUnreachable ||
|
||||
return inst->opcode() == spv::Op::OpUnreachable ||
|
||||
!spvOpcodeIsAbort(inst->opcode());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class InlinePass : public Pass {
|
||||
|
||||
// Add pointer to type to module and return resultId. Returns 0 if the type
|
||||
// could not be created.
|
||||
uint32_t AddPointerToType(uint32_t type_id, SpvStorageClass storage_class);
|
||||
uint32_t AddPointerToType(uint32_t type_id, spv::StorageClass storage_class);
|
||||
|
||||
// Add unconditional branch to labelId to end of block block_ptr.
|
||||
void AddBranch(uint32_t labelId, std::unique_ptr<BasicBlock>* block_ptr);
|
||||
|
||||
@@ -16,31 +16,29 @@
|
||||
|
||||
#include "inst_bindless_check_pass.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Input Operand Indices
|
||||
static const int kSpvImageSampleImageIdInIdx = 0;
|
||||
static const int kSpvSampledImageImageIdInIdx = 0;
|
||||
static const int kSpvSampledImageSamplerIdInIdx = 1;
|
||||
static const int kSpvImageSampledImageIdInIdx = 0;
|
||||
static const int kSpvCopyObjectOperandIdInIdx = 0;
|
||||
static const int kSpvLoadPtrIdInIdx = 0;
|
||||
static const int kSpvAccessChainBaseIdInIdx = 0;
|
||||
static const int kSpvAccessChainIndex0IdInIdx = 1;
|
||||
static const int kSpvTypeArrayTypeIdInIdx = 0;
|
||||
static const int kSpvTypeArrayLengthIdInIdx = 1;
|
||||
static const int kSpvConstantValueInIdx = 0;
|
||||
static const int kSpvVariableStorageClassInIdx = 0;
|
||||
static const int kSpvTypePtrTypeIdInIdx = 1;
|
||||
static const int kSpvTypeImageDim = 1;
|
||||
static const int kSpvTypeImageDepth = 2;
|
||||
static const int kSpvTypeImageArrayed = 3;
|
||||
static const int kSpvTypeImageMS = 4;
|
||||
static const int kSpvTypeImageSampled = 5;
|
||||
} // anonymous namespace
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
// Input Operand Indices
|
||||
constexpr int kSpvImageSampleImageIdInIdx = 0;
|
||||
constexpr int kSpvSampledImageImageIdInIdx = 0;
|
||||
constexpr int kSpvSampledImageSamplerIdInIdx = 1;
|
||||
constexpr int kSpvImageSampledImageIdInIdx = 0;
|
||||
constexpr int kSpvCopyObjectOperandIdInIdx = 0;
|
||||
constexpr int kSpvLoadPtrIdInIdx = 0;
|
||||
constexpr int kSpvAccessChainBaseIdInIdx = 0;
|
||||
constexpr int kSpvAccessChainIndex0IdInIdx = 1;
|
||||
constexpr int kSpvTypeArrayTypeIdInIdx = 0;
|
||||
constexpr int kSpvTypeArrayLengthIdInIdx = 1;
|
||||
constexpr int kSpvConstantValueInIdx = 0;
|
||||
constexpr int kSpvVariableStorageClassInIdx = 0;
|
||||
constexpr int kSpvTypePtrTypeIdInIdx = 1;
|
||||
constexpr int kSpvTypeImageDim = 1;
|
||||
constexpr int kSpvTypeImageDepth = 2;
|
||||
constexpr int kSpvTypeImageArrayed = 3;
|
||||
constexpr int kSpvTypeImageMS = 4;
|
||||
constexpr int kSpvTypeImageSampled = 5;
|
||||
} // namespace
|
||||
|
||||
uint32_t InstBindlessCheckPass::GenDebugReadLength(
|
||||
uint32_t var_id, InstructionBuilder* builder) {
|
||||
@@ -79,25 +77,25 @@ uint32_t InstBindlessCheckPass::CloneOriginalImage(
|
||||
uint32_t old_image_id, InstructionBuilder* builder) {
|
||||
Instruction* new_image_inst;
|
||||
Instruction* old_image_inst = get_def_use_mgr()->GetDef(old_image_id);
|
||||
if (old_image_inst->opcode() == SpvOpLoad) {
|
||||
if (old_image_inst->opcode() == spv::Op::OpLoad) {
|
||||
new_image_inst = builder->AddLoad(
|
||||
old_image_inst->type_id(),
|
||||
old_image_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx));
|
||||
} else if (old_image_inst->opcode() == SpvOp::SpvOpSampledImage) {
|
||||
} else if (old_image_inst->opcode() == spv::Op::OpSampledImage) {
|
||||
uint32_t clone_id = CloneOriginalImage(
|
||||
old_image_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx),
|
||||
builder);
|
||||
new_image_inst = builder->AddBinaryOp(
|
||||
old_image_inst->type_id(), SpvOpSampledImage, clone_id,
|
||||
old_image_inst->type_id(), spv::Op::OpSampledImage, clone_id,
|
||||
old_image_inst->GetSingleWordInOperand(kSpvSampledImageSamplerIdInIdx));
|
||||
} else if (old_image_inst->opcode() == SpvOp::SpvOpImage) {
|
||||
} else if (old_image_inst->opcode() == spv::Op::OpImage) {
|
||||
uint32_t clone_id = CloneOriginalImage(
|
||||
old_image_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx),
|
||||
builder);
|
||||
new_image_inst =
|
||||
builder->AddUnaryOp(old_image_inst->type_id(), SpvOpImage, clone_id);
|
||||
new_image_inst = builder->AddUnaryOp(old_image_inst->type_id(),
|
||||
spv::Op::OpImage, clone_id);
|
||||
} else {
|
||||
assert(old_image_inst->opcode() == SpvOp::SpvOpCopyObject &&
|
||||
assert(old_image_inst->opcode() == spv::Op::OpCopyObject &&
|
||||
"expecting OpCopyObject");
|
||||
uint32_t clone_id = CloneOriginalImage(
|
||||
old_image_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx),
|
||||
@@ -143,38 +141,38 @@ uint32_t InstBindlessCheckPass::CloneOriginalReference(
|
||||
|
||||
uint32_t InstBindlessCheckPass::GetImageId(Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOp::SpvOpImageSampleImplicitLod:
|
||||
case SpvOp::SpvOpImageSampleExplicitLod:
|
||||
case SpvOp::SpvOpImageSampleDrefImplicitLod:
|
||||
case SpvOp::SpvOpImageSampleDrefExplicitLod:
|
||||
case SpvOp::SpvOpImageSampleProjImplicitLod:
|
||||
case SpvOp::SpvOpImageSampleProjExplicitLod:
|
||||
case SpvOp::SpvOpImageSampleProjDrefImplicitLod:
|
||||
case SpvOp::SpvOpImageSampleProjDrefExplicitLod:
|
||||
case SpvOp::SpvOpImageGather:
|
||||
case SpvOp::SpvOpImageDrefGather:
|
||||
case SpvOp::SpvOpImageQueryLod:
|
||||
case SpvOp::SpvOpImageSparseSampleImplicitLod:
|
||||
case SpvOp::SpvOpImageSparseSampleExplicitLod:
|
||||
case SpvOp::SpvOpImageSparseSampleDrefImplicitLod:
|
||||
case SpvOp::SpvOpImageSparseSampleDrefExplicitLod:
|
||||
case SpvOp::SpvOpImageSparseSampleProjImplicitLod:
|
||||
case SpvOp::SpvOpImageSparseSampleProjExplicitLod:
|
||||
case SpvOp::SpvOpImageSparseSampleProjDrefImplicitLod:
|
||||
case SpvOp::SpvOpImageSparseSampleProjDrefExplicitLod:
|
||||
case SpvOp::SpvOpImageSparseGather:
|
||||
case SpvOp::SpvOpImageSparseDrefGather:
|
||||
case SpvOp::SpvOpImageFetch:
|
||||
case SpvOp::SpvOpImageRead:
|
||||
case SpvOp::SpvOpImageQueryFormat:
|
||||
case SpvOp::SpvOpImageQueryOrder:
|
||||
case SpvOp::SpvOpImageQuerySizeLod:
|
||||
case SpvOp::SpvOpImageQuerySize:
|
||||
case SpvOp::SpvOpImageQueryLevels:
|
||||
case SpvOp::SpvOpImageQuerySamples:
|
||||
case SpvOp::SpvOpImageSparseFetch:
|
||||
case SpvOp::SpvOpImageSparseRead:
|
||||
case SpvOp::SpvOpImageWrite:
|
||||
case spv::Op::OpImageSampleImplicitLod:
|
||||
case spv::Op::OpImageSampleExplicitLod:
|
||||
case spv::Op::OpImageSampleDrefImplicitLod:
|
||||
case spv::Op::OpImageSampleDrefExplicitLod:
|
||||
case spv::Op::OpImageSampleProjImplicitLod:
|
||||
case spv::Op::OpImageSampleProjExplicitLod:
|
||||
case spv::Op::OpImageSampleProjDrefImplicitLod:
|
||||
case spv::Op::OpImageSampleProjDrefExplicitLod:
|
||||
case spv::Op::OpImageGather:
|
||||
case spv::Op::OpImageDrefGather:
|
||||
case spv::Op::OpImageQueryLod:
|
||||
case spv::Op::OpImageSparseSampleImplicitLod:
|
||||
case spv::Op::OpImageSparseSampleExplicitLod:
|
||||
case spv::Op::OpImageSparseSampleDrefImplicitLod:
|
||||
case spv::Op::OpImageSparseSampleDrefExplicitLod:
|
||||
case spv::Op::OpImageSparseSampleProjImplicitLod:
|
||||
case spv::Op::OpImageSparseSampleProjExplicitLod:
|
||||
case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
|
||||
case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
|
||||
case spv::Op::OpImageSparseGather:
|
||||
case spv::Op::OpImageSparseDrefGather:
|
||||
case spv::Op::OpImageFetch:
|
||||
case spv::Op::OpImageRead:
|
||||
case spv::Op::OpImageQueryFormat:
|
||||
case spv::Op::OpImageQueryOrder:
|
||||
case spv::Op::OpImageQuerySizeLod:
|
||||
case spv::Op::OpImageQuerySize:
|
||||
case spv::Op::OpImageQueryLevels:
|
||||
case spv::Op::OpImageQuerySamples:
|
||||
case spv::Op::OpImageSparseFetch:
|
||||
case spv::Op::OpImageSparseRead:
|
||||
case spv::Op::OpImageWrite:
|
||||
return inst->GetSingleWordInOperand(kSpvImageSampleImageIdInIdx);
|
||||
default:
|
||||
break;
|
||||
@@ -190,56 +188,58 @@ Instruction* InstBindlessCheckPass::GetPointeeTypeInst(Instruction* ptr_inst) {
|
||||
bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
|
||||
RefAnalysis* ref) {
|
||||
ref->ref_inst = ref_inst;
|
||||
if (ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) {
|
||||
if (ref_inst->opcode() == spv::Op::OpLoad ||
|
||||
ref_inst->opcode() == spv::Op::OpStore) {
|
||||
ref->desc_load_id = 0;
|
||||
ref->ptr_id = ref_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx);
|
||||
Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref->ptr_id);
|
||||
if (ptr_inst->opcode() != SpvOp::SpvOpAccessChain) return false;
|
||||
if (ptr_inst->opcode() != spv::Op::OpAccessChain) return false;
|
||||
ref->var_id = ptr_inst->GetSingleWordInOperand(kSpvAccessChainBaseIdInIdx);
|
||||
Instruction* var_inst = get_def_use_mgr()->GetDef(ref->var_id);
|
||||
if (var_inst->opcode() != SpvOp::SpvOpVariable) return false;
|
||||
uint32_t storage_class =
|
||||
var_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx);
|
||||
if (var_inst->opcode() != spv::Op::OpVariable) return false;
|
||||
spv::StorageClass storage_class = spv::StorageClass(
|
||||
var_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx));
|
||||
switch (storage_class) {
|
||||
case SpvStorageClassUniform:
|
||||
case SpvStorageClassStorageBuffer:
|
||||
case spv::StorageClass::Uniform:
|
||||
case spv::StorageClass::StorageBuffer:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
// Check for deprecated storage block form
|
||||
if (storage_class == SpvStorageClassUniform) {
|
||||
if (storage_class == spv::StorageClass::Uniform) {
|
||||
uint32_t var_ty_id = var_inst->type_id();
|
||||
Instruction* var_ty_inst = get_def_use_mgr()->GetDef(var_ty_id);
|
||||
uint32_t ptr_ty_id =
|
||||
var_ty_inst->GetSingleWordInOperand(kSpvTypePtrTypeIdInIdx);
|
||||
Instruction* ptr_ty_inst = get_def_use_mgr()->GetDef(ptr_ty_id);
|
||||
SpvOp ptr_ty_op = ptr_ty_inst->opcode();
|
||||
spv::Op ptr_ty_op = ptr_ty_inst->opcode();
|
||||
uint32_t block_ty_id =
|
||||
(ptr_ty_op == SpvOpTypeArray || ptr_ty_op == SpvOpTypeRuntimeArray)
|
||||
(ptr_ty_op == spv::Op::OpTypeArray ||
|
||||
ptr_ty_op == spv::Op::OpTypeRuntimeArray)
|
||||
? ptr_ty_inst->GetSingleWordInOperand(kSpvTypeArrayTypeIdInIdx)
|
||||
: ptr_ty_id;
|
||||
assert(get_def_use_mgr()->GetDef(block_ty_id)->opcode() ==
|
||||
SpvOpTypeStruct &&
|
||||
spv::Op::OpTypeStruct &&
|
||||
"unexpected block type");
|
||||
bool block_found = get_decoration_mgr()->FindDecoration(
|
||||
block_ty_id, SpvDecorationBlock,
|
||||
block_ty_id, uint32_t(spv::Decoration::Block),
|
||||
[](const Instruction&) { return true; });
|
||||
if (!block_found) {
|
||||
// If block decoration not found, verify deprecated form of SSBO
|
||||
bool buffer_block_found = get_decoration_mgr()->FindDecoration(
|
||||
block_ty_id, SpvDecorationBufferBlock,
|
||||
block_ty_id, uint32_t(spv::Decoration::BufferBlock),
|
||||
[](const Instruction&) { return true; });
|
||||
USE_ASSERT(buffer_block_found && "block decoration not found");
|
||||
storage_class = SpvStorageClassStorageBuffer;
|
||||
storage_class = spv::StorageClass::StorageBuffer;
|
||||
}
|
||||
}
|
||||
ref->strg_class = storage_class;
|
||||
ref->strg_class = uint32_t(storage_class);
|
||||
Instruction* desc_type_inst = GetPointeeTypeInst(var_inst);
|
||||
switch (desc_type_inst->opcode()) {
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
// A load through a descriptor array will have at least 3 operands. We
|
||||
// do not want to instrument loads of descriptors here which are part of
|
||||
// an image-based reference.
|
||||
@@ -261,29 +261,29 @@ bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
|
||||
Instruction* desc_load_inst;
|
||||
for (;;) {
|
||||
desc_load_inst = get_def_use_mgr()->GetDef(desc_load_id);
|
||||
if (desc_load_inst->opcode() == SpvOp::SpvOpSampledImage)
|
||||
if (desc_load_inst->opcode() == spv::Op::OpSampledImage)
|
||||
desc_load_id =
|
||||
desc_load_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx);
|
||||
else if (desc_load_inst->opcode() == SpvOp::SpvOpImage)
|
||||
else if (desc_load_inst->opcode() == spv::Op::OpImage)
|
||||
desc_load_id =
|
||||
desc_load_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx);
|
||||
else if (desc_load_inst->opcode() == SpvOp::SpvOpCopyObject)
|
||||
else if (desc_load_inst->opcode() == spv::Op::OpCopyObject)
|
||||
desc_load_id =
|
||||
desc_load_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (desc_load_inst->opcode() != SpvOp::SpvOpLoad) {
|
||||
if (desc_load_inst->opcode() != spv::Op::OpLoad) {
|
||||
// TODO(greg-lunarg): Handle additional possibilities?
|
||||
return false;
|
||||
}
|
||||
ref->desc_load_id = desc_load_id;
|
||||
ref->ptr_id = desc_load_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx);
|
||||
Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref->ptr_id);
|
||||
if (ptr_inst->opcode() == SpvOp::SpvOpVariable) {
|
||||
if (ptr_inst->opcode() == spv::Op::OpVariable) {
|
||||
ref->desc_idx_id = 0;
|
||||
ref->var_id = ref->ptr_id;
|
||||
} else if (ptr_inst->opcode() == SpvOp::SpvOpAccessChain) {
|
||||
} else if (ptr_inst->opcode() == spv::Op::OpAccessChain) {
|
||||
if (ptr_inst->NumInOperands() != 2) {
|
||||
assert(false && "unexpected bindless index number");
|
||||
return false;
|
||||
@@ -292,7 +292,7 @@ bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
|
||||
ptr_inst->GetSingleWordInOperand(kSpvAccessChainIndex0IdInIdx);
|
||||
ref->var_id = ptr_inst->GetSingleWordInOperand(kSpvAccessChainBaseIdInIdx);
|
||||
Instruction* var_inst = get_def_use_mgr()->GetDef(ref->var_id);
|
||||
if (var_inst->opcode() != SpvOpVariable) {
|
||||
if (var_inst->opcode() != spv::Op::OpVariable) {
|
||||
assert(false && "unexpected bindless base");
|
||||
return false;
|
||||
}
|
||||
@@ -369,13 +369,13 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
|
||||
uint32_t buff_ty_id;
|
||||
uint32_t ac_in_idx = 1;
|
||||
switch (desc_ty_inst->opcode()) {
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
buff_ty_id = desc_ty_inst->GetSingleWordInOperand(0);
|
||||
++ac_in_idx;
|
||||
break;
|
||||
default:
|
||||
assert(desc_ty_inst->opcode() == SpvOpTypeStruct &&
|
||||
assert(desc_ty_inst->opcode() == spv::Op::OpTypeStruct &&
|
||||
"unexpected descriptor type");
|
||||
buff_ty_id = desc_ty_inst->result_id();
|
||||
break;
|
||||
@@ -393,19 +393,20 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
|
||||
Instruction* curr_ty_inst = get_def_use_mgr()->GetDef(curr_ty_id);
|
||||
uint32_t curr_offset_id = 0;
|
||||
switch (curr_ty_inst->opcode()) {
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray: {
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray: {
|
||||
// Get array stride and multiply by current index
|
||||
uint32_t arr_stride = FindStride(curr_ty_id, SpvDecorationArrayStride);
|
||||
uint32_t arr_stride =
|
||||
FindStride(curr_ty_id, uint32_t(spv::Decoration::ArrayStride));
|
||||
uint32_t arr_stride_id = builder->GetUintConstantId(arr_stride);
|
||||
uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
|
||||
Instruction* curr_offset_inst = builder->AddBinaryOp(
|
||||
GetUintId(), SpvOpIMul, arr_stride_id, curr_idx_32b_id);
|
||||
GetUintId(), spv::Op::OpIMul, arr_stride_id, curr_idx_32b_id);
|
||||
curr_offset_id = curr_offset_inst->result_id();
|
||||
// Get element type for next step
|
||||
curr_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
|
||||
} break;
|
||||
case SpvOpTypeMatrix: {
|
||||
case spv::Op::OpTypeMatrix: {
|
||||
assert(matrix_stride != 0 && "missing matrix stride");
|
||||
matrix_stride_id = builder->GetUintConstantId(matrix_stride);
|
||||
uint32_t vec_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
|
||||
@@ -423,40 +424,40 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
|
||||
}
|
||||
uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
|
||||
Instruction* curr_offset_inst = builder->AddBinaryOp(
|
||||
GetUintId(), SpvOpIMul, col_stride_id, curr_idx_32b_id);
|
||||
GetUintId(), spv::Op::OpIMul, col_stride_id, curr_idx_32b_id);
|
||||
curr_offset_id = curr_offset_inst->result_id();
|
||||
// Get element type for next step
|
||||
curr_ty_id = vec_ty_id;
|
||||
in_matrix = true;
|
||||
} break;
|
||||
case SpvOpTypeVector: {
|
||||
case spv::Op::OpTypeVector: {
|
||||
// If inside a row major matrix type, multiply index by matrix stride,
|
||||
// else multiply by component size
|
||||
uint32_t comp_ty_id = curr_ty_inst->GetSingleWordInOperand(0u);
|
||||
uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
|
||||
if (in_matrix && !col_major) {
|
||||
Instruction* curr_offset_inst = builder->AddBinaryOp(
|
||||
GetUintId(), SpvOpIMul, matrix_stride_id, curr_idx_32b_id);
|
||||
GetUintId(), spv::Op::OpIMul, matrix_stride_id, curr_idx_32b_id);
|
||||
curr_offset_id = curr_offset_inst->result_id();
|
||||
} else {
|
||||
uint32_t comp_ty_sz = ByteSize(comp_ty_id, 0u, false, false);
|
||||
uint32_t comp_ty_sz_id = builder->GetUintConstantId(comp_ty_sz);
|
||||
Instruction* curr_offset_inst = builder->AddBinaryOp(
|
||||
GetUintId(), SpvOpIMul, comp_ty_sz_id, curr_idx_32b_id);
|
||||
GetUintId(), spv::Op::OpIMul, comp_ty_sz_id, curr_idx_32b_id);
|
||||
curr_offset_id = curr_offset_inst->result_id();
|
||||
}
|
||||
// Get element type for next step
|
||||
curr_ty_id = comp_ty_id;
|
||||
} break;
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
// Get buffer byte offset for the referenced member
|
||||
Instruction* curr_idx_inst = get_def_use_mgr()->GetDef(curr_idx_id);
|
||||
assert(curr_idx_inst->opcode() == SpvOpConstant &&
|
||||
assert(curr_idx_inst->opcode() == spv::Op::OpConstant &&
|
||||
"unexpected struct index");
|
||||
uint32_t member_idx = curr_idx_inst->GetSingleWordInOperand(0);
|
||||
uint32_t member_offset = 0xdeadbeef;
|
||||
bool found = get_decoration_mgr()->FindDecoration(
|
||||
curr_ty_id, SpvDecorationOffset,
|
||||
curr_ty_id, uint32_t(spv::Decoration::Offset),
|
||||
[&member_idx, &member_offset](const Instruction& deco_inst) {
|
||||
if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
|
||||
return false;
|
||||
@@ -470,7 +471,7 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
|
||||
// enclosing struct type at the member index. If none found, reset
|
||||
// stride to 0.
|
||||
found = get_decoration_mgr()->FindDecoration(
|
||||
curr_ty_id, SpvDecorationMatrixStride,
|
||||
curr_ty_id, uint32_t(spv::Decoration::MatrixStride),
|
||||
[&member_idx, &matrix_stride](const Instruction& deco_inst) {
|
||||
if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
|
||||
return false;
|
||||
@@ -480,7 +481,7 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
|
||||
if (!found) matrix_stride = 0;
|
||||
// Look for column major decoration
|
||||
found = get_decoration_mgr()->FindDecoration(
|
||||
curr_ty_id, SpvDecorationColMajor,
|
||||
curr_ty_id, uint32_t(spv::Decoration::ColMajor),
|
||||
[&member_idx, &col_major](const Instruction& deco_inst) {
|
||||
if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
|
||||
return false;
|
||||
@@ -496,8 +497,8 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
|
||||
if (sum_id == 0)
|
||||
sum_id = curr_offset_id;
|
||||
else {
|
||||
Instruction* sum_inst =
|
||||
builder->AddBinaryOp(GetUintId(), SpvOpIAdd, sum_id, curr_offset_id);
|
||||
Instruction* sum_inst = builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd,
|
||||
sum_id, curr_offset_id);
|
||||
sum_id = sum_inst->result_id();
|
||||
}
|
||||
++ac_in_idx;
|
||||
@@ -507,7 +508,7 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
|
||||
uint32_t last = bsize - 1;
|
||||
uint32_t last_id = builder->GetUintConstantId(last);
|
||||
Instruction* sum_inst =
|
||||
builder->AddBinaryOp(GetUintId(), SpvOpIAdd, sum_id, last_id);
|
||||
builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, sum_id, last_id);
|
||||
return sum_inst->result_id();
|
||||
}
|
||||
|
||||
@@ -527,8 +528,9 @@ void InstBindlessCheckPass::GenCheckCode(
|
||||
std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
|
||||
std::unique_ptr<Instruction> valid_label(NewLabel(valid_blk_id));
|
||||
std::unique_ptr<Instruction> invalid_label(NewLabel(invalid_blk_id));
|
||||
(void)builder.AddConditionalBranch(check_id, valid_blk_id, invalid_blk_id,
|
||||
merge_blk_id, SpvSelectionControlMaskNone);
|
||||
(void)builder.AddConditionalBranch(
|
||||
check_id, valid_blk_id, invalid_blk_id, merge_blk_id,
|
||||
uint32_t(spv::SelectionControlMask::MaskNone));
|
||||
// Gen valid bounds branch
|
||||
std::unique_ptr<BasicBlock> new_blk_ptr(
|
||||
new BasicBlock(std::move(valid_label)));
|
||||
@@ -593,24 +595,24 @@ void InstBindlessCheckPass::GenDescIdxCheckCode(
|
||||
RefAnalysis ref;
|
||||
if (!AnalyzeDescriptorReference(&*ref_inst_itr, &ref)) return;
|
||||
Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref.ptr_id);
|
||||
if (ptr_inst->opcode() != SpvOp::SpvOpAccessChain) return;
|
||||
if (ptr_inst->opcode() != spv::Op::OpAccessChain) return;
|
||||
// If index and bound both compile-time constants and index < bound,
|
||||
// return without changing
|
||||
Instruction* var_inst = get_def_use_mgr()->GetDef(ref.var_id);
|
||||
Instruction* desc_type_inst = GetPointeeTypeInst(var_inst);
|
||||
uint32_t length_id = 0;
|
||||
if (desc_type_inst->opcode() == SpvOpTypeArray) {
|
||||
if (desc_type_inst->opcode() == spv::Op::OpTypeArray) {
|
||||
length_id =
|
||||
desc_type_inst->GetSingleWordInOperand(kSpvTypeArrayLengthIdInIdx);
|
||||
Instruction* index_inst = get_def_use_mgr()->GetDef(ref.desc_idx_id);
|
||||
Instruction* length_inst = get_def_use_mgr()->GetDef(length_id);
|
||||
if (index_inst->opcode() == SpvOpConstant &&
|
||||
length_inst->opcode() == SpvOpConstant &&
|
||||
if (index_inst->opcode() == spv::Op::OpConstant &&
|
||||
length_inst->opcode() == spv::Op::OpConstant &&
|
||||
index_inst->GetSingleWordInOperand(kSpvConstantValueInIdx) <
|
||||
length_inst->GetSingleWordInOperand(kSpvConstantValueInIdx))
|
||||
return;
|
||||
} else if (!desc_idx_enabled_ ||
|
||||
desc_type_inst->opcode() != SpvOpTypeRuntimeArray) {
|
||||
desc_type_inst->opcode() != spv::Op::OpTypeRuntimeArray) {
|
||||
return;
|
||||
}
|
||||
// Move original block's preceding instructions into first new block
|
||||
@@ -624,7 +626,7 @@ void InstBindlessCheckPass::GenDescIdxCheckCode(
|
||||
// If length id not yet set, descriptor array is runtime size so
|
||||
// generate load of length from stage's debug input buffer.
|
||||
if (length_id == 0) {
|
||||
assert(desc_type_inst->opcode() == SpvOpTypeRuntimeArray &&
|
||||
assert(desc_type_inst->opcode() == spv::Op::OpTypeRuntimeArray &&
|
||||
"unexpected bindless type");
|
||||
length_id = GenDebugReadLength(ref.var_id, &builder);
|
||||
}
|
||||
@@ -633,7 +635,7 @@ void InstBindlessCheckPass::GenDescIdxCheckCode(
|
||||
// for the referenced value.
|
||||
uint32_t desc_idx_32b_id = Gen32BitCvtCode(ref.desc_idx_id, &builder);
|
||||
uint32_t length_32b_id = Gen32BitCvtCode(length_id, &builder);
|
||||
Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), SpvOpULessThan,
|
||||
Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan,
|
||||
desc_idx_32b_id, length_32b_id);
|
||||
ref.desc_idx_id = desc_idx_32b_id;
|
||||
GenCheckCode(ult_inst->result_id(), error_id, 0u, length_id, stage_idx, &ref,
|
||||
@@ -661,9 +663,10 @@ void InstBindlessCheckPass::GenDescInitCheckCode(
|
||||
// TODO(greg-lunarg): Do bounds check for aggregate loads and stores
|
||||
Instruction* ref_ptr_inst = get_def_use_mgr()->GetDef(ref.ptr_id);
|
||||
Instruction* pte_type_inst = GetPointeeTypeInst(ref_ptr_inst);
|
||||
uint32_t pte_type_op = pte_type_inst->opcode();
|
||||
if (pte_type_op == SpvOpTypeArray || pte_type_op == SpvOpTypeRuntimeArray ||
|
||||
pte_type_op == SpvOpTypeStruct)
|
||||
spv::Op pte_type_op = pte_type_inst->opcode();
|
||||
if (pte_type_op == spv::Op::OpTypeArray ||
|
||||
pte_type_op == spv::Op::OpTypeRuntimeArray ||
|
||||
pte_type_op == spv::Op::OpTypeStruct)
|
||||
init_check = true;
|
||||
}
|
||||
// If initialization check and not enabled, return
|
||||
@@ -687,11 +690,13 @@ void InstBindlessCheckPass::GenDescInitCheckCode(
|
||||
// being full reference and false branch being debug output and zero
|
||||
// for the referenced value.
|
||||
Instruction* ult_inst =
|
||||
builder.AddBinaryOp(GetBoolId(), SpvOpULessThan, ref_id, init_id);
|
||||
uint32_t error = init_check ? kInstErrorBindlessUninit
|
||||
: (ref.strg_class == SpvStorageClassUniform
|
||||
? kInstErrorBuffOOBUniform
|
||||
: kInstErrorBuffOOBStorage);
|
||||
builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan, ref_id, init_id);
|
||||
uint32_t error =
|
||||
init_check
|
||||
? kInstErrorBindlessUninit
|
||||
: (spv::StorageClass(ref.strg_class) == spv::StorageClass::Uniform
|
||||
? kInstErrorBuffOOBUniform
|
||||
: kInstErrorBuffOOBStorage);
|
||||
uint32_t error_id = builder.GetUintConstantId(error);
|
||||
GenCheckCode(ult_inst->result_id(), error_id, init_check ? 0 : ref_id,
|
||||
init_check ? builder.GetUintConstantId(0u) : init_id, stage_idx,
|
||||
@@ -708,11 +713,11 @@ void InstBindlessCheckPass::GenTexBuffCheckCode(
|
||||
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
|
||||
// Only process OpImageRead and OpImageWrite with no optional operands
|
||||
Instruction* ref_inst = &*ref_inst_itr;
|
||||
SpvOp op = ref_inst->opcode();
|
||||
spv::Op op = ref_inst->opcode();
|
||||
uint32_t num_in_oprnds = ref_inst->NumInOperands();
|
||||
if (!((op == SpvOpImageRead && num_in_oprnds == 2) ||
|
||||
(op == SpvOpImageFetch && num_in_oprnds == 2) ||
|
||||
(op == SpvOpImageWrite && num_in_oprnds == 3)))
|
||||
if (!((op == spv::Op::OpImageRead && num_in_oprnds == 2) ||
|
||||
(op == spv::Op::OpImageFetch && num_in_oprnds == 2) ||
|
||||
(op == spv::Op::OpImageWrite && num_in_oprnds == 3)))
|
||||
return;
|
||||
// Pull components from descriptor reference
|
||||
RefAnalysis ref;
|
||||
@@ -721,17 +726,20 @@ void InstBindlessCheckPass::GenTexBuffCheckCode(
|
||||
Instruction* image_inst = get_def_use_mgr()->GetDef(ref.image_id);
|
||||
uint32_t image_ty_id = image_inst->type_id();
|
||||
Instruction* image_ty_inst = get_def_use_mgr()->GetDef(image_ty_id);
|
||||
if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDim) != SpvDimBuffer)
|
||||
if (spv::Dim(image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDim)) !=
|
||||
spv::Dim::Buffer) {
|
||||
return;
|
||||
}
|
||||
if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDepth) != 0) return;
|
||||
if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageArrayed) != 0) return;
|
||||
if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageMS) != 0) return;
|
||||
// Enable ImageQuery Capability if not yet enabled
|
||||
if (!get_feature_mgr()->HasCapability(SpvCapabilityImageQuery)) {
|
||||
std::unique_ptr<Instruction> cap_image_query_inst(new Instruction(
|
||||
context(), SpvOpCapability, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}}));
|
||||
if (!get_feature_mgr()->HasCapability(spv::Capability::ImageQuery)) {
|
||||
std::unique_ptr<Instruction> cap_image_query_inst(
|
||||
new Instruction(context(), spv::Op::OpCapability, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_CAPABILITY,
|
||||
{uint32_t(spv::Capability::ImageQuery)}}}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*cap_image_query_inst);
|
||||
context()->AddCapability(std::move(cap_image_query_inst));
|
||||
}
|
||||
@@ -750,13 +758,13 @@ void InstBindlessCheckPass::GenTexBuffCheckCode(
|
||||
if (ref.desc_idx_id == 0) ref.desc_idx_id = builder.GetUintConstantId(0u);
|
||||
// Get texel buffer size.
|
||||
Instruction* size_inst =
|
||||
builder.AddUnaryOp(GetUintId(), SpvOpImageQuerySize, ref.image_id);
|
||||
builder.AddUnaryOp(GetUintId(), spv::Op::OpImageQuerySize, ref.image_id);
|
||||
uint32_t size_id = size_inst->result_id();
|
||||
// Generate runtime initialization/bounds test code with true branch
|
||||
// being full reference and false branch being debug output and zero
|
||||
// for the referenced value.
|
||||
Instruction* ult_inst =
|
||||
builder.AddBinaryOp(GetBoolId(), SpvOpULessThan, coord_id, size_id);
|
||||
builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan, coord_id, size_id);
|
||||
uint32_t error =
|
||||
(image_ty_inst->GetSingleWordInOperand(kSpvTypeImageSampled) == 2)
|
||||
? kInstErrorBuffOOBStorageTexel
|
||||
@@ -778,13 +786,16 @@ void InstBindlessCheckPass::InitializeInstBindlessCheck() {
|
||||
// init check is enabled.
|
||||
if (desc_idx_enabled_ || buffer_bounds_enabled_ || texel_buffer_enabled_)
|
||||
for (auto& anno : get_module()->annotations())
|
||||
if (anno.opcode() == SpvOpDecorate) {
|
||||
if (anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet)
|
||||
if (anno.opcode() == spv::Op::OpDecorate) {
|
||||
if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::DescriptorSet) {
|
||||
var2desc_set_[anno.GetSingleWordInOperand(0u)] =
|
||||
anno.GetSingleWordInOperand(2u);
|
||||
else if (anno.GetSingleWordInOperand(1u) == SpvDecorationBinding)
|
||||
} else if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
|
||||
spv::Decoration::Binding) {
|
||||
var2binding_[anno.GetSingleWordInOperand(0u)] =
|
||||
anno.GetSingleWordInOperand(2u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ namespace opt {
|
||||
uint32_t InstBuffAddrCheckPass::CloneOriginalReference(
|
||||
Instruction* ref_inst, InstructionBuilder* builder) {
|
||||
// Clone original ref with new result id (if load)
|
||||
assert(
|
||||
(ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) &&
|
||||
"unexpected ref");
|
||||
assert((ref_inst->opcode() == spv::Op::OpLoad ||
|
||||
ref_inst->opcode() == spv::Op::OpStore) &&
|
||||
"unexpected ref");
|
||||
std::unique_ptr<Instruction> new_ref_inst(ref_inst->Clone(context()));
|
||||
uint32_t ref_result_id = ref_inst->result_id();
|
||||
uint32_t new_ref_id = 0;
|
||||
@@ -41,16 +41,17 @@ uint32_t InstBuffAddrCheckPass::CloneOriginalReference(
|
||||
}
|
||||
|
||||
bool InstBuffAddrCheckPass::IsPhysicalBuffAddrReference(Instruction* ref_inst) {
|
||||
if (ref_inst->opcode() != SpvOpLoad && ref_inst->opcode() != SpvOpStore)
|
||||
if (ref_inst->opcode() != spv::Op::OpLoad &&
|
||||
ref_inst->opcode() != spv::Op::OpStore)
|
||||
return false;
|
||||
uint32_t ptr_id = ref_inst->GetSingleWordInOperand(0);
|
||||
analysis::DefUseManager* du_mgr = get_def_use_mgr();
|
||||
Instruction* ptr_inst = du_mgr->GetDef(ptr_id);
|
||||
if (ptr_inst->opcode() != SpvOpAccessChain) return false;
|
||||
if (ptr_inst->opcode() != spv::Op::OpAccessChain) return false;
|
||||
uint32_t ptr_ty_id = ptr_inst->type_id();
|
||||
Instruction* ptr_ty_inst = du_mgr->GetDef(ptr_ty_id);
|
||||
if (ptr_ty_inst->GetSingleWordInOperand(0) !=
|
||||
SpvStorageClassPhysicalStorageBufferEXT)
|
||||
if (spv::StorageClass(ptr_ty_inst->GetSingleWordInOperand(0)) !=
|
||||
spv::StorageClass::PhysicalStorageBufferEXT)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -72,8 +73,9 @@ void InstBuffAddrCheckPass::GenCheckCode(
|
||||
std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
|
||||
std::unique_ptr<Instruction> valid_label(NewLabel(valid_blk_id));
|
||||
std::unique_ptr<Instruction> invalid_label(NewLabel(invalid_blk_id));
|
||||
(void)builder.AddConditionalBranch(check_id, valid_blk_id, invalid_blk_id,
|
||||
merge_blk_id, SpvSelectionControlMaskNone);
|
||||
(void)builder.AddConditionalBranch(
|
||||
check_id, valid_blk_id, invalid_blk_id, merge_blk_id,
|
||||
uint32_t(spv::SelectionControlMask::MaskNone));
|
||||
// Gen valid branch
|
||||
std::unique_ptr<BasicBlock> new_blk_ptr(
|
||||
new BasicBlock(std::move(valid_label)));
|
||||
@@ -86,12 +88,12 @@ void InstBuffAddrCheckPass::GenCheckCode(
|
||||
builder.SetInsertPoint(&*new_blk_ptr);
|
||||
// Convert uptr from uint64 to 2 uint32
|
||||
Instruction* lo_uptr_inst =
|
||||
builder.AddUnaryOp(GetUintId(), SpvOpUConvert, ref_uptr_id);
|
||||
builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, ref_uptr_id);
|
||||
Instruction* rshift_uptr_inst =
|
||||
builder.AddBinaryOp(GetUint64Id(), SpvOpShiftRightLogical, ref_uptr_id,
|
||||
builder.GetUintConstantId(32));
|
||||
Instruction* hi_uptr_inst = builder.AddUnaryOp(GetUintId(), SpvOpUConvert,
|
||||
rshift_uptr_inst->result_id());
|
||||
builder.AddBinaryOp(GetUint64Id(), spv::Op::OpShiftRightLogical,
|
||||
ref_uptr_id, builder.GetUintConstantId(32));
|
||||
Instruction* hi_uptr_inst = builder.AddUnaryOp(
|
||||
GetUintId(), spv::Op::OpUConvert, rshift_uptr_inst->result_id());
|
||||
GenDebugStreamWrite(
|
||||
uid2offset_[ref_inst->unique_id()], stage_idx,
|
||||
{error_id, lo_uptr_inst->result_id(), hi_uptr_inst->result_id()},
|
||||
@@ -105,8 +107,8 @@ void InstBuffAddrCheckPass::GenCheckCode(
|
||||
analysis::Type* ref_type = type_mgr->GetType(ref_type_id);
|
||||
if (ref_type->AsPointer() != nullptr) {
|
||||
uint32_t null_u64_id = GetNullId(GetUint64Id());
|
||||
Instruction* null_ptr_inst =
|
||||
builder.AddUnaryOp(ref_type_id, SpvOpConvertUToPtr, null_u64_id);
|
||||
Instruction* null_ptr_inst = builder.AddUnaryOp(
|
||||
ref_type_id, spv::Op::OpConvertUToPtr, null_u64_id);
|
||||
null_id = null_ptr_inst->result_id();
|
||||
} else {
|
||||
null_id = GetNullId(ref_type_id);
|
||||
@@ -133,16 +135,16 @@ void InstBuffAddrCheckPass::GenCheckCode(
|
||||
uint32_t InstBuffAddrCheckPass::GetTypeAlignment(uint32_t type_id) {
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeVector:
|
||||
case spv::Op::OpTypeFloat:
|
||||
case spv::Op::OpTypeInt:
|
||||
case spv::Op::OpTypeVector:
|
||||
return GetTypeLength(type_id);
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
return GetTypeAlignment(type_inst->GetSingleWordInOperand(0));
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
return GetTypeAlignment(type_inst->GetSingleWordInOperand(0));
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
uint32_t max = 0;
|
||||
type_inst->ForEachInId([&max, this](const uint32_t* iid) {
|
||||
uint32_t alignment = GetTypeAlignment(*iid);
|
||||
@@ -150,9 +152,9 @@ uint32_t InstBuffAddrCheckPass::GetTypeAlignment(uint32_t type_id) {
|
||||
});
|
||||
return max;
|
||||
}
|
||||
case SpvOpTypePointer:
|
||||
assert(type_inst->GetSingleWordInOperand(0) ==
|
||||
SpvStorageClassPhysicalStorageBufferEXT &&
|
||||
case spv::Op::OpTypePointer:
|
||||
assert(spv::StorageClass(type_inst->GetSingleWordInOperand(0)) ==
|
||||
spv::StorageClass::PhysicalStorageBufferEXT &&
|
||||
"unexpected pointer type");
|
||||
return 8u;
|
||||
default:
|
||||
@@ -164,29 +166,29 @@ uint32_t InstBuffAddrCheckPass::GetTypeAlignment(uint32_t type_id) {
|
||||
uint32_t InstBuffAddrCheckPass::GetTypeLength(uint32_t type_id) {
|
||||
Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
|
||||
switch (type_inst->opcode()) {
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeInt:
|
||||
case spv::Op::OpTypeFloat:
|
||||
case spv::Op::OpTypeInt:
|
||||
return type_inst->GetSingleWordInOperand(0) / 8u;
|
||||
case SpvOpTypeVector: {
|
||||
case spv::Op::OpTypeVector: {
|
||||
uint32_t raw_cnt = type_inst->GetSingleWordInOperand(1);
|
||||
uint32_t adj_cnt = (raw_cnt == 3u) ? 4u : raw_cnt;
|
||||
return adj_cnt * GetTypeLength(type_inst->GetSingleWordInOperand(0));
|
||||
}
|
||||
case SpvOpTypeMatrix:
|
||||
case spv::Op::OpTypeMatrix:
|
||||
return type_inst->GetSingleWordInOperand(1) *
|
||||
GetTypeLength(type_inst->GetSingleWordInOperand(0));
|
||||
case SpvOpTypePointer:
|
||||
assert(type_inst->GetSingleWordInOperand(0) ==
|
||||
SpvStorageClassPhysicalStorageBufferEXT &&
|
||||
case spv::Op::OpTypePointer:
|
||||
assert(spv::StorageClass(type_inst->GetSingleWordInOperand(0)) ==
|
||||
spv::StorageClass::PhysicalStorageBufferEXT &&
|
||||
"unexpected pointer type");
|
||||
return 8u;
|
||||
case SpvOpTypeArray: {
|
||||
case spv::Op::OpTypeArray: {
|
||||
uint32_t const_id = type_inst->GetSingleWordInOperand(1);
|
||||
Instruction* const_inst = get_def_use_mgr()->GetDef(const_id);
|
||||
uint32_t cnt = const_inst->GetSingleWordInOperand(0);
|
||||
return cnt * GetTypeLength(type_inst->GetSingleWordInOperand(0));
|
||||
}
|
||||
case SpvOpTypeStruct: {
|
||||
case spv::Op::OpTypeStruct: {
|
||||
uint32_t len = 0;
|
||||
type_inst->ForEachInId([&len, this](const uint32_t* iid) {
|
||||
// Align struct length
|
||||
@@ -200,7 +202,7 @@ uint32_t InstBuffAddrCheckPass::GetTypeLength(uint32_t type_id) {
|
||||
});
|
||||
return len;
|
||||
}
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case spv::Op::OpTypeRuntimeArray:
|
||||
default:
|
||||
assert(false && "unexpected type");
|
||||
return 0;
|
||||
@@ -213,7 +215,7 @@ void InstBuffAddrCheckPass::AddParam(uint32_t type_id,
|
||||
uint32_t pid = TakeNextId();
|
||||
param_vec->push_back(pid);
|
||||
std::unique_ptr<Instruction> param_inst(new Instruction(
|
||||
get_module()->context(), SpvOpFunctionParameter, type_id, pid, {}));
|
||||
get_module()->context(), spv::Op::OpFunctionParameter, type_id, pid, {}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
|
||||
(*input_func)->AddParameter(std::move(param_inst));
|
||||
}
|
||||
@@ -231,10 +233,10 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
|
||||
analysis::Function func_ty(type_mgr->GetType(GetBoolId()), param_types);
|
||||
analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
|
||||
std::unique_ptr<Instruction> func_inst(
|
||||
new Instruction(get_module()->context(), SpvOpFunction, GetBoolId(),
|
||||
search_test_func_id_,
|
||||
new Instruction(get_module()->context(), spv::Op::OpFunction,
|
||||
GetBoolId(), search_test_func_id_,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
{SpvFunctionControlMaskNone}},
|
||||
{uint32_t(spv::FunctionControlMask::MaskNone)}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
|
||||
{type_mgr->GetTypeInstruction(reg_func_ty)}}}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
|
||||
@@ -256,7 +258,7 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
|
||||
// Branch to search loop header
|
||||
std::unique_ptr<Instruction> hdr_blk_label(NewLabel(hdr_blk_id));
|
||||
(void)builder.AddInstruction(MakeUnique<Instruction>(
|
||||
context(), SpvOpBranch, 0, 0,
|
||||
context(), spv::Op::OpBranch, 0, 0,
|
||||
std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {hdr_blk_id}}}));
|
||||
input_func->AddBasicBlock(std::move(first_blk_ptr));
|
||||
// Linear search loop header block
|
||||
@@ -273,12 +275,12 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
|
||||
uint32_t idx_phi_id = TakeNextId();
|
||||
uint32_t idx_inc_id = TakeNextId();
|
||||
std::unique_ptr<Instruction> idx_inc_inst(new Instruction(
|
||||
context(), SpvOpIAdd, GetUintId(), idx_inc_id,
|
||||
context(), spv::Op::OpIAdd, GetUintId(), idx_inc_id,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {idx_phi_id}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
|
||||
{builder.GetUintConstantId(1u)}}}));
|
||||
std::unique_ptr<Instruction> idx_phi_inst(new Instruction(
|
||||
context(), SpvOpPhi, GetUintId(), idx_phi_id,
|
||||
context(), spv::Op::OpPhi, GetUintId(), idx_phi_id,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
|
||||
{builder.GetUintConstantId(1u)}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {first_blk_id}},
|
||||
@@ -292,14 +294,15 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
|
||||
std::unique_ptr<Instruction> bound_test_blk_label(
|
||||
NewLabel(bound_test_blk_id));
|
||||
(void)builder.AddInstruction(MakeUnique<Instruction>(
|
||||
context(), SpvOpLoopMerge, 0, 0,
|
||||
context(), spv::Op::OpLoopMerge, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {bound_test_blk_id}},
|
||||
{SPV_OPERAND_TYPE_ID, {cont_blk_id}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {SpvLoopControlMaskNone}}}));
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
{uint32_t(spv::LoopControlMask::MaskNone)}}}));
|
||||
// Branch to continue/work block
|
||||
(void)builder.AddInstruction(MakeUnique<Instruction>(
|
||||
context(), SpvOpBranch, 0, 0,
|
||||
context(), spv::Op::OpBranch, 0, 0,
|
||||
std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_blk_id}}}));
|
||||
input_func->AddBasicBlock(std::move(hdr_blk_ptr));
|
||||
// Continue/Work Block. Read next buffer pointer and break if greater
|
||||
@@ -313,19 +316,19 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
|
||||
uint32_t ibuf_id = GetInputBufferId();
|
||||
uint32_t ibuf_ptr_id = GetInputBufferPtrId();
|
||||
Instruction* uptr_ac_inst = builder.AddTernaryOp(
|
||||
ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
|
||||
ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
|
||||
builder.GetUintConstantId(kDebugInputDataOffset), idx_inc_id);
|
||||
uint32_t ibuf_type_id = GetInputBufferTypeId();
|
||||
Instruction* uptr_load_inst =
|
||||
builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, uptr_ac_inst->result_id());
|
||||
Instruction* uptr_load_inst = builder.AddUnaryOp(
|
||||
ibuf_type_id, spv::Op::OpLoad, uptr_ac_inst->result_id());
|
||||
// If loaded address greater than ref_ptr arg, break, else branch back to
|
||||
// loop header
|
||||
Instruction* uptr_test_inst =
|
||||
builder.AddBinaryOp(GetBoolId(), SpvOpUGreaterThan,
|
||||
builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThan,
|
||||
uptr_load_inst->result_id(), param_vec[0]);
|
||||
(void)builder.AddConditionalBranch(uptr_test_inst->result_id(),
|
||||
bound_test_blk_id, hdr_blk_id,
|
||||
kInvalidId, SpvSelectionControlMaskNone);
|
||||
(void)builder.AddConditionalBranch(
|
||||
uptr_test_inst->result_id(), bound_test_blk_id, hdr_blk_id, kInvalidId,
|
||||
uint32_t(spv::SelectionControlMask::MaskNone));
|
||||
input_func->AddBasicBlock(std::move(cont_blk_ptr));
|
||||
// Bounds test block. Read length of selected buffer and test that
|
||||
// all len arg bytes are in buffer.
|
||||
@@ -333,63 +336,65 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
|
||||
MakeUnique<BasicBlock>(std::move(bound_test_blk_label));
|
||||
builder.SetInsertPoint(&*bound_test_blk_ptr);
|
||||
// Decrement index to point to previous/candidate buffer address
|
||||
Instruction* cand_idx_inst = builder.AddBinaryOp(
|
||||
GetUintId(), SpvOpISub, idx_inc_id, builder.GetUintConstantId(1u));
|
||||
Instruction* cand_idx_inst =
|
||||
builder.AddBinaryOp(GetUintId(), spv::Op::OpISub, idx_inc_id,
|
||||
builder.GetUintConstantId(1u));
|
||||
// Load candidate buffer address
|
||||
Instruction* cand_ac_inst =
|
||||
builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
|
||||
builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
|
||||
builder.GetUintConstantId(kDebugInputDataOffset),
|
||||
cand_idx_inst->result_id());
|
||||
Instruction* cand_load_inst =
|
||||
builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, cand_ac_inst->result_id());
|
||||
Instruction* cand_load_inst = builder.AddUnaryOp(
|
||||
ibuf_type_id, spv::Op::OpLoad, cand_ac_inst->result_id());
|
||||
// Compute offset of ref_ptr from candidate buffer address
|
||||
Instruction* offset_inst = builder.AddBinaryOp(
|
||||
ibuf_type_id, SpvOpISub, param_vec[0], cand_load_inst->result_id());
|
||||
Instruction* offset_inst =
|
||||
builder.AddBinaryOp(ibuf_type_id, spv::Op::OpISub, param_vec[0],
|
||||
cand_load_inst->result_id());
|
||||
// Convert ref length to uint64
|
||||
Instruction* ref_len_64_inst =
|
||||
builder.AddUnaryOp(ibuf_type_id, SpvOpUConvert, param_vec[1]);
|
||||
builder.AddUnaryOp(ibuf_type_id, spv::Op::OpUConvert, param_vec[1]);
|
||||
// Add ref length to ref offset to compute end of reference
|
||||
Instruction* ref_end_inst =
|
||||
builder.AddBinaryOp(ibuf_type_id, SpvOpIAdd, offset_inst->result_id(),
|
||||
ref_len_64_inst->result_id());
|
||||
Instruction* ref_end_inst = builder.AddBinaryOp(
|
||||
ibuf_type_id, spv::Op::OpIAdd, offset_inst->result_id(),
|
||||
ref_len_64_inst->result_id());
|
||||
// Load starting index of lengths in input buffer and convert to uint32
|
||||
Instruction* len_start_ac_inst =
|
||||
builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
|
||||
builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
|
||||
builder.GetUintConstantId(kDebugInputDataOffset),
|
||||
builder.GetUintConstantId(0u));
|
||||
Instruction* len_start_load_inst = builder.AddUnaryOp(
|
||||
ibuf_type_id, SpvOpLoad, len_start_ac_inst->result_id());
|
||||
ibuf_type_id, spv::Op::OpLoad, len_start_ac_inst->result_id());
|
||||
Instruction* len_start_32_inst = builder.AddUnaryOp(
|
||||
GetUintId(), SpvOpUConvert, len_start_load_inst->result_id());
|
||||
GetUintId(), spv::Op::OpUConvert, len_start_load_inst->result_id());
|
||||
// Decrement search index to get candidate buffer length index
|
||||
Instruction* cand_len_idx_inst =
|
||||
builder.AddBinaryOp(GetUintId(), SpvOpISub, cand_idx_inst->result_id(),
|
||||
builder.GetUintConstantId(1u));
|
||||
Instruction* cand_len_idx_inst = builder.AddBinaryOp(
|
||||
GetUintId(), spv::Op::OpISub, cand_idx_inst->result_id(),
|
||||
builder.GetUintConstantId(1u));
|
||||
// Add candidate length index to start index
|
||||
Instruction* len_idx_inst = builder.AddBinaryOp(
|
||||
GetUintId(), SpvOpIAdd, cand_len_idx_inst->result_id(),
|
||||
GetUintId(), spv::Op::OpIAdd, cand_len_idx_inst->result_id(),
|
||||
len_start_32_inst->result_id());
|
||||
// Load candidate buffer length
|
||||
Instruction* len_ac_inst =
|
||||
builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
|
||||
builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
|
||||
builder.GetUintConstantId(kDebugInputDataOffset),
|
||||
len_idx_inst->result_id());
|
||||
Instruction* len_load_inst =
|
||||
builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, len_ac_inst->result_id());
|
||||
Instruction* len_load_inst = builder.AddUnaryOp(
|
||||
ibuf_type_id, spv::Op::OpLoad, len_ac_inst->result_id());
|
||||
// Test if reference end within candidate buffer length
|
||||
Instruction* len_test_inst = builder.AddBinaryOp(
|
||||
GetBoolId(), SpvOpULessThanEqual, ref_end_inst->result_id(),
|
||||
GetBoolId(), spv::Op::OpULessThanEqual, ref_end_inst->result_id(),
|
||||
len_load_inst->result_id());
|
||||
// Return test result
|
||||
(void)builder.AddInstruction(MakeUnique<Instruction>(
|
||||
context(), SpvOpReturnValue, 0, 0,
|
||||
context(), spv::Op::OpReturnValue, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {len_test_inst->result_id()}}}));
|
||||
// Close block
|
||||
input_func->AddBasicBlock(std::move(bound_test_blk_ptr));
|
||||
// Close function and add function to module
|
||||
std::unique_ptr<Instruction> func_end_inst(
|
||||
new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
|
||||
std::unique_ptr<Instruction> func_end_inst(new Instruction(
|
||||
get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
|
||||
input_func->SetFunctionEnd(std::move(func_end_inst));
|
||||
context()->AddFunction(std::move(input_func));
|
||||
@@ -403,18 +408,18 @@ uint32_t InstBuffAddrCheckPass::GenSearchAndTest(Instruction* ref_inst,
|
||||
InstructionBuilder* builder,
|
||||
uint32_t* ref_uptr_id) {
|
||||
// Enable Int64 if necessary
|
||||
if (!get_feature_mgr()->HasCapability(SpvCapabilityInt64)) {
|
||||
if (!get_feature_mgr()->HasCapability(spv::Capability::Int64)) {
|
||||
std::unique_ptr<Instruction> cap_int64_inst(new Instruction(
|
||||
context(), SpvOpCapability, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityInt64}}}));
|
||||
context(), spv::Op::OpCapability, 0, 0,
|
||||
std::initializer_list<Operand>{{SPV_OPERAND_TYPE_CAPABILITY,
|
||||
{uint32_t(spv::Capability::Int64)}}}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*cap_int64_inst);
|
||||
context()->AddCapability(std::move(cap_int64_inst));
|
||||
}
|
||||
// Convert reference pointer to uint64
|
||||
uint32_t ref_ptr_id = ref_inst->GetSingleWordInOperand(0);
|
||||
Instruction* ref_uptr_inst =
|
||||
builder->AddUnaryOp(GetUint64Id(), SpvOpConvertPtrToU, ref_ptr_id);
|
||||
builder->AddUnaryOp(GetUint64Id(), spv::Op::OpConvertPtrToU, ref_ptr_id);
|
||||
*ref_uptr_id = ref_uptr_inst->result_id();
|
||||
// Compute reference length in bytes
|
||||
analysis::DefUseManager* du_mgr = get_def_use_mgr();
|
||||
@@ -427,7 +432,7 @@ uint32_t InstBuffAddrCheckPass::GenSearchAndTest(Instruction* ref_inst,
|
||||
const std::vector<uint32_t> args = {GetSearchAndTestFuncId(), *ref_uptr_id,
|
||||
ref_len_id};
|
||||
Instruction* call_inst =
|
||||
builder->AddNaryOp(GetBoolId(), SpvOpFunctionCall, args);
|
||||
builder->AddNaryOp(GetBoolId(), spv::Op::OpFunctionCall, args);
|
||||
uint32_t retval = call_inst->result_id();
|
||||
return retval;
|
||||
}
|
||||
@@ -485,7 +490,7 @@ Pass::Status InstBuffAddrCheckPass::ProcessImpl() {
|
||||
|
||||
Pass::Status InstBuffAddrCheckPass::Process() {
|
||||
if (!get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityPhysicalStorageBufferAddressesEXT))
|
||||
spv::Capability::PhysicalStorageBufferAddressesEXT))
|
||||
return Status::SuccessWithoutChange;
|
||||
InitInstBuffAddrCheck();
|
||||
return ProcessImpl();
|
||||
|
||||
@@ -35,7 +35,7 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
|
||||
uint32_t c_ty_id = type_mgr->GetId(c_ty);
|
||||
for (uint32_t c = 0; c < v_ty->element_count(); ++c) {
|
||||
Instruction* c_inst = builder->AddIdLiteralOp(
|
||||
c_ty_id, SpvOpCompositeExtract, val_inst->result_id(), c);
|
||||
c_ty_id, spv::Op::OpCompositeExtract, val_inst->result_id(), c);
|
||||
GenOutputValues(c_inst, val_ids, builder);
|
||||
}
|
||||
return;
|
||||
@@ -44,8 +44,9 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
|
||||
// Select between uint32 zero or one
|
||||
uint32_t zero_id = builder->GetUintConstantId(0);
|
||||
uint32_t one_id = builder->GetUintConstantId(1);
|
||||
Instruction* sel_inst = builder->AddTernaryOp(
|
||||
GetUintId(), SpvOpSelect, val_inst->result_id(), one_id, zero_id);
|
||||
Instruction* sel_inst =
|
||||
builder->AddTernaryOp(GetUintId(), spv::Op::OpSelect,
|
||||
val_inst->result_id(), one_id, zero_id);
|
||||
val_ids->push_back(sel_inst->result_id());
|
||||
return;
|
||||
}
|
||||
@@ -55,21 +56,21 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
|
||||
case 16: {
|
||||
// Convert float16 to float32 and recurse
|
||||
Instruction* f32_inst = builder->AddUnaryOp(
|
||||
GetFloatId(), SpvOpFConvert, val_inst->result_id());
|
||||
GetFloatId(), spv::Op::OpFConvert, val_inst->result_id());
|
||||
GenOutputValues(f32_inst, val_ids, builder);
|
||||
return;
|
||||
}
|
||||
case 64: {
|
||||
// Bitcast float64 to uint64 and recurse
|
||||
Instruction* ui64_inst = builder->AddUnaryOp(
|
||||
GetUint64Id(), SpvOpBitcast, val_inst->result_id());
|
||||
GetUint64Id(), spv::Op::OpBitcast, val_inst->result_id());
|
||||
GenOutputValues(ui64_inst, val_ids, builder);
|
||||
return;
|
||||
}
|
||||
case 32: {
|
||||
// Bitcase float32 to uint32
|
||||
Instruction* bc_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast,
|
||||
val_inst->result_id());
|
||||
Instruction* bc_inst = builder->AddUnaryOp(
|
||||
GetUintId(), spv::Op::OpBitcast, val_inst->result_id());
|
||||
val_ids->push_back(bc_inst->result_id());
|
||||
return;
|
||||
}
|
||||
@@ -85,17 +86,17 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
|
||||
Instruction* ui64_inst = val_inst;
|
||||
if (i_ty->IsSigned()) {
|
||||
// Bitcast sint64 to uint64
|
||||
ui64_inst = builder->AddUnaryOp(GetUint64Id(), SpvOpBitcast,
|
||||
ui64_inst = builder->AddUnaryOp(GetUint64Id(), spv::Op::OpBitcast,
|
||||
val_inst->result_id());
|
||||
}
|
||||
// Break uint64 into 2x uint32
|
||||
Instruction* lo_ui64_inst = builder->AddUnaryOp(
|
||||
GetUintId(), SpvOpUConvert, ui64_inst->result_id());
|
||||
GetUintId(), spv::Op::OpUConvert, ui64_inst->result_id());
|
||||
Instruction* rshift_ui64_inst = builder->AddBinaryOp(
|
||||
GetUint64Id(), SpvOpShiftRightLogical, ui64_inst->result_id(),
|
||||
builder->GetUintConstantId(32));
|
||||
GetUint64Id(), spv::Op::OpShiftRightLogical,
|
||||
ui64_inst->result_id(), builder->GetUintConstantId(32));
|
||||
Instruction* hi_ui64_inst = builder->AddUnaryOp(
|
||||
GetUintId(), SpvOpUConvert, rshift_ui64_inst->result_id());
|
||||
GetUintId(), spv::Op::OpUConvert, rshift_ui64_inst->result_id());
|
||||
val_ids->push_back(lo_ui64_inst->result_id());
|
||||
val_ids->push_back(hi_ui64_inst->result_id());
|
||||
return;
|
||||
@@ -104,12 +105,12 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
|
||||
Instruction* ui8_inst = val_inst;
|
||||
if (i_ty->IsSigned()) {
|
||||
// Bitcast sint8 to uint8
|
||||
ui8_inst = builder->AddUnaryOp(GetUint8Id(), SpvOpBitcast,
|
||||
ui8_inst = builder->AddUnaryOp(GetUint8Id(), spv::Op::OpBitcast,
|
||||
val_inst->result_id());
|
||||
}
|
||||
// Convert uint8 to uint32
|
||||
Instruction* ui32_inst = builder->AddUnaryOp(
|
||||
GetUintId(), SpvOpUConvert, ui8_inst->result_id());
|
||||
GetUintId(), spv::Op::OpUConvert, ui8_inst->result_id());
|
||||
val_ids->push_back(ui32_inst->result_id());
|
||||
return;
|
||||
}
|
||||
@@ -117,7 +118,7 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
|
||||
Instruction* ui32_inst = val_inst;
|
||||
if (i_ty->IsSigned()) {
|
||||
// Bitcast sint32 to uint32
|
||||
ui32_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast,
|
||||
ui32_inst = builder->AddUnaryOp(GetUintId(), spv::Op::OpBitcast,
|
||||
val_inst->result_id());
|
||||
}
|
||||
// uint32 needs no further processing
|
||||
@@ -158,7 +159,7 @@ void InstDebugPrintfPass::GenOutputCode(
|
||||
return;
|
||||
}
|
||||
Instruction* opnd_inst = get_def_use_mgr()->GetDef(*iid);
|
||||
if (opnd_inst->opcode() == SpvOpString) {
|
||||
if (opnd_inst->opcode() == spv::Op::OpString) {
|
||||
uint32_t string_id_id = builder.GetUintConstantId(*iid);
|
||||
val_ids.push_back(string_id_id);
|
||||
} else {
|
||||
@@ -176,7 +177,7 @@ void InstDebugPrintfPass::GenDebugPrintfCode(
|
||||
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
|
||||
// If not DebugPrintf OpExtInst, return.
|
||||
Instruction* printf_inst = &*ref_inst_itr;
|
||||
if (printf_inst->opcode() != SpvOpExtInst) return;
|
||||
if (printf_inst->opcode() != spv::Op::OpExtInst) return;
|
||||
if (printf_inst->GetSingleWordInOperand(0) != ext_inst_printf_id_) return;
|
||||
if (printf_inst->GetSingleWordInOperand(1) !=
|
||||
NonSemanticDebugPrintfDebugPrintf)
|
||||
|
||||
462
3rdparty/spirv-tools/source/opt/instruction.cpp
vendored
462
3rdparty/spirv-tools/source/opt/instruction.cpp
vendored
@@ -24,38 +24,37 @@
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
// Indices used to get particular operands out of instructions using InOperand.
|
||||
const uint32_t kTypeImageDimIndex = 1;
|
||||
const uint32_t kLoadBaseIndex = 0;
|
||||
const uint32_t kPointerTypeStorageClassIndex = 0;
|
||||
const uint32_t kVariableStorageClassIndex = 0;
|
||||
const uint32_t kTypeImageSampledIndex = 5;
|
||||
constexpr uint32_t kTypeImageDimIndex = 1;
|
||||
constexpr uint32_t kLoadBaseIndex = 0;
|
||||
constexpr uint32_t kPointerTypeStorageClassIndex = 0;
|
||||
constexpr uint32_t kVariableStorageClassIndex = 0;
|
||||
constexpr uint32_t kTypeImageSampledIndex = 5;
|
||||
|
||||
// Constants for OpenCL.DebugInfo.100 / NonSemantic.Shader.DebugInfo.100
|
||||
// extension instructions.
|
||||
const uint32_t kExtInstSetIdInIdx = 0;
|
||||
const uint32_t kExtInstInstructionInIdx = 1;
|
||||
const uint32_t kDebugScopeNumWords = 7;
|
||||
const uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
|
||||
const uint32_t kDebugNoScopeNumWords = 5;
|
||||
constexpr uint32_t kExtInstSetIdInIdx = 0;
|
||||
constexpr uint32_t kExtInstInstructionInIdx = 1;
|
||||
constexpr uint32_t kDebugScopeNumWords = 7;
|
||||
constexpr uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
|
||||
constexpr uint32_t kDebugNoScopeNumWords = 5;
|
||||
|
||||
// Number of operands of an OpBranchConditional instruction
|
||||
// with weights.
|
||||
const uint32_t kOpBranchConditionalWithWeightsNumOperands = 5;
|
||||
constexpr uint32_t kOpBranchConditionalWithWeightsNumOperands = 5;
|
||||
} // namespace
|
||||
|
||||
Instruction::Instruction(IRContext* c)
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
context_(c),
|
||||
opcode_(SpvOpNop),
|
||||
opcode_(spv::Op::OpNop),
|
||||
has_type_id_(false),
|
||||
has_result_id_(false),
|
||||
unique_id_(c->TakeNextUniqueId()),
|
||||
dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
|
||||
|
||||
Instruction::Instruction(IRContext* c, SpvOp op)
|
||||
Instruction::Instruction(IRContext* c, spv::Op op)
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
context_(c),
|
||||
opcode_(op),
|
||||
@@ -68,12 +67,13 @@ Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
|
||||
std::vector<Instruction>&& dbg_line)
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
context_(c),
|
||||
opcode_(static_cast<SpvOp>(inst.opcode)),
|
||||
opcode_(static_cast<spv::Op>(inst.opcode)),
|
||||
has_type_id_(inst.type_id != 0),
|
||||
has_result_id_(inst.result_id != 0),
|
||||
unique_id_(c->TakeNextUniqueId()),
|
||||
dbg_line_insts_(std::move(dbg_line)),
|
||||
dbg_scope_(kNoDebugScope, kNoInlinedAt) {
|
||||
operands_.reserve(inst.num_operands);
|
||||
for (uint32_t i = 0; i < inst.num_operands; ++i) {
|
||||
const auto& current_payload = inst.operands[i];
|
||||
operands_.emplace_back(
|
||||
@@ -88,11 +88,12 @@ Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
|
||||
const DebugScope& dbg_scope)
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
context_(c),
|
||||
opcode_(static_cast<SpvOp>(inst.opcode)),
|
||||
opcode_(static_cast<spv::Op>(inst.opcode)),
|
||||
has_type_id_(inst.type_id != 0),
|
||||
has_result_id_(inst.result_id != 0),
|
||||
unique_id_(c->TakeNextUniqueId()),
|
||||
dbg_scope_(dbg_scope) {
|
||||
operands_.reserve(inst.num_operands);
|
||||
for (uint32_t i = 0; i < inst.num_operands; ++i) {
|
||||
const auto& current_payload = inst.operands[i];
|
||||
operands_.emplace_back(
|
||||
@@ -101,7 +102,7 @@ Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
|
||||
}
|
||||
}
|
||||
|
||||
Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
|
||||
Instruction::Instruction(IRContext* c, spv::Op op, uint32_t ty_id,
|
||||
uint32_t res_id, const OperandList& in_operands)
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
context_(c),
|
||||
@@ -111,6 +112,14 @@ Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
|
||||
unique_id_(c->TakeNextUniqueId()),
|
||||
operands_(),
|
||||
dbg_scope_(kNoDebugScope, kNoInlinedAt) {
|
||||
size_t operands_size = in_operands.size();
|
||||
if (has_type_id_) {
|
||||
operands_size++;
|
||||
}
|
||||
if (has_result_id_) {
|
||||
operands_size++;
|
||||
}
|
||||
operands_.reserve(operands_size);
|
||||
if (has_type_id_) {
|
||||
operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
|
||||
std::initializer_list<uint32_t>{ty_id});
|
||||
@@ -179,7 +188,7 @@ uint32_t Instruction::NumInOperandWords() const {
|
||||
}
|
||||
|
||||
bool Instruction::HasBranchWeights() const {
|
||||
if (opcode_ == SpvOpBranchConditional &&
|
||||
if (opcode_ == spv::Op::OpBranchConditional &&
|
||||
NumOperands() == kOpBranchConditionalWithWeightsNumOperands) {
|
||||
return true;
|
||||
}
|
||||
@@ -208,13 +217,13 @@ bool Instruction::IsReadOnlyLoad() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (address_def->opcode() == SpvOpVariable) {
|
||||
if (address_def->opcode() == spv::Op::OpVariable) {
|
||||
if (address_def->IsReadOnlyPointer()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (address_def->opcode() == SpvOpLoad) {
|
||||
if (address_def->opcode() == spv::Op::OpLoad) {
|
||||
const analysis::Type* address_type =
|
||||
context()->get_type_mgr()->GetType(address_def->type_id());
|
||||
if (address_type->AsSampledImage() != nullptr) {
|
||||
@@ -235,12 +244,12 @@ Instruction* Instruction::GetBaseAddress() const {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
switch (base_inst->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpInBoundsPtrAccessChain:
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpCopyObject:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpPtrAccessChain:
|
||||
case spv::Op::OpInBoundsPtrAccessChain:
|
||||
case spv::Op::OpImageTexelPointer:
|
||||
case spv::Op::OpCopyObject:
|
||||
// All of these instructions have the base pointer use a base pointer
|
||||
// in in-operand 0.
|
||||
base = base_inst->GetSingleWordInOperand(0);
|
||||
@@ -255,20 +264,20 @@ Instruction* Instruction::GetBaseAddress() const {
|
||||
}
|
||||
|
||||
bool Instruction::IsReadOnlyPointer() const {
|
||||
if (context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
|
||||
if (context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
|
||||
return IsReadOnlyPointerShaders();
|
||||
else
|
||||
return IsReadOnlyPointerKernel();
|
||||
}
|
||||
|
||||
bool Instruction::IsVulkanStorageImage() const {
|
||||
if (opcode() != SpvOpTypePointer) {
|
||||
if (opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class =
|
||||
GetSingleWordInOperand(kPointerTypeStorageClassIndex);
|
||||
if (storage_class != SpvStorageClassUniformConstant) {
|
||||
spv::StorageClass storage_class =
|
||||
spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
|
||||
if (storage_class != spv::StorageClass::UniformConstant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -276,17 +285,18 @@ bool Instruction::IsVulkanStorageImage() const {
|
||||
context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
|
||||
|
||||
// Unpack the optional layer of arraying.
|
||||
if (base_type->opcode() == SpvOpTypeArray ||
|
||||
base_type->opcode() == SpvOpTypeRuntimeArray) {
|
||||
if (base_type->opcode() == spv::Op::OpTypeArray ||
|
||||
base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
|
||||
base_type = context()->get_def_use_mgr()->GetDef(
|
||||
base_type->GetSingleWordInOperand(0));
|
||||
}
|
||||
|
||||
if (base_type->opcode() != SpvOpTypeImage) {
|
||||
if (base_type->opcode() != spv::Op::OpTypeImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
|
||||
if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
|
||||
spv::Dim::Buffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -296,13 +306,13 @@ bool Instruction::IsVulkanStorageImage() const {
|
||||
}
|
||||
|
||||
bool Instruction::IsVulkanSampledImage() const {
|
||||
if (opcode() != SpvOpTypePointer) {
|
||||
if (opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class =
|
||||
GetSingleWordInOperand(kPointerTypeStorageClassIndex);
|
||||
if (storage_class != SpvStorageClassUniformConstant) {
|
||||
spv::StorageClass storage_class =
|
||||
spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
|
||||
if (storage_class != spv::StorageClass::UniformConstant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -310,17 +320,18 @@ bool Instruction::IsVulkanSampledImage() const {
|
||||
context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
|
||||
|
||||
// Unpack the optional layer of arraying.
|
||||
if (base_type->opcode() == SpvOpTypeArray ||
|
||||
base_type->opcode() == SpvOpTypeRuntimeArray) {
|
||||
if (base_type->opcode() == spv::Op::OpTypeArray ||
|
||||
base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
|
||||
base_type = context()->get_def_use_mgr()->GetDef(
|
||||
base_type->GetSingleWordInOperand(0));
|
||||
}
|
||||
|
||||
if (base_type->opcode() != SpvOpTypeImage) {
|
||||
if (base_type->opcode() != spv::Op::OpTypeImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
|
||||
if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
|
||||
spv::Dim::Buffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -330,13 +341,13 @@ bool Instruction::IsVulkanSampledImage() const {
|
||||
}
|
||||
|
||||
bool Instruction::IsVulkanStorageTexelBuffer() const {
|
||||
if (opcode() != SpvOpTypePointer) {
|
||||
if (opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class =
|
||||
GetSingleWordInOperand(kPointerTypeStorageClassIndex);
|
||||
if (storage_class != SpvStorageClassUniformConstant) {
|
||||
spv::StorageClass storage_class =
|
||||
spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
|
||||
if (storage_class != spv::StorageClass::UniformConstant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -344,17 +355,18 @@ bool Instruction::IsVulkanStorageTexelBuffer() const {
|
||||
context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
|
||||
|
||||
// Unpack the optional layer of arraying.
|
||||
if (base_type->opcode() == SpvOpTypeArray ||
|
||||
base_type->opcode() == SpvOpTypeRuntimeArray) {
|
||||
if (base_type->opcode() == spv::Op::OpTypeArray ||
|
||||
base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
|
||||
base_type = context()->get_def_use_mgr()->GetDef(
|
||||
base_type->GetSingleWordInOperand(0));
|
||||
}
|
||||
|
||||
if (base_type->opcode() != SpvOpTypeImage) {
|
||||
if (base_type->opcode() != spv::Op::OpTypeImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) != SpvDimBuffer) {
|
||||
if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) !=
|
||||
spv::Dim::Buffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -366,7 +378,7 @@ bool Instruction::IsVulkanStorageTexelBuffer() const {
|
||||
bool Instruction::IsVulkanStorageBuffer() const {
|
||||
// Is there a difference between a "Storage buffer" and a "dynamic storage
|
||||
// buffer" in SPIR-V and do we care about the difference?
|
||||
if (opcode() != SpvOpTypePointer) {
|
||||
if (opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -374,28 +386,28 @@ bool Instruction::IsVulkanStorageBuffer() const {
|
||||
context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
|
||||
|
||||
// Unpack the optional layer of arraying.
|
||||
if (base_type->opcode() == SpvOpTypeArray ||
|
||||
base_type->opcode() == SpvOpTypeRuntimeArray) {
|
||||
if (base_type->opcode() == spv::Op::OpTypeArray ||
|
||||
base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
|
||||
base_type = context()->get_def_use_mgr()->GetDef(
|
||||
base_type->GetSingleWordInOperand(0));
|
||||
}
|
||||
|
||||
if (base_type->opcode() != SpvOpTypeStruct) {
|
||||
if (base_type->opcode() != spv::Op::OpTypeStruct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class =
|
||||
GetSingleWordInOperand(kPointerTypeStorageClassIndex);
|
||||
if (storage_class == SpvStorageClassUniform) {
|
||||
spv::StorageClass storage_class =
|
||||
spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
|
||||
if (storage_class == spv::StorageClass::Uniform) {
|
||||
bool is_buffer_block = false;
|
||||
context()->get_decoration_mgr()->ForEachDecoration(
|
||||
base_type->result_id(), SpvDecorationBufferBlock,
|
||||
base_type->result_id(), uint32_t(spv::Decoration::BufferBlock),
|
||||
[&is_buffer_block](const Instruction&) { is_buffer_block = true; });
|
||||
return is_buffer_block;
|
||||
} else if (storage_class == SpvStorageClassStorageBuffer) {
|
||||
} else if (storage_class == spv::StorageClass::StorageBuffer) {
|
||||
bool is_block = false;
|
||||
context()->get_decoration_mgr()->ForEachDecoration(
|
||||
base_type->result_id(), SpvDecorationBlock,
|
||||
base_type->result_id(), uint32_t(spv::Decoration::Block),
|
||||
[&is_block](const Instruction&) { is_block = true; });
|
||||
return is_block;
|
||||
}
|
||||
@@ -403,13 +415,14 @@ bool Instruction::IsVulkanStorageBuffer() const {
|
||||
}
|
||||
|
||||
bool Instruction::IsVulkanStorageBufferVariable() const {
|
||||
if (opcode() != SpvOpVariable) {
|
||||
if (opcode() != spv::Op::OpVariable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class = GetSingleWordInOperand(kVariableStorageClassIndex);
|
||||
if (storage_class == SpvStorageClassStorageBuffer ||
|
||||
storage_class == SpvStorageClassUniform) {
|
||||
spv::StorageClass storage_class =
|
||||
spv::StorageClass(GetSingleWordInOperand(kVariableStorageClassIndex));
|
||||
if (storage_class == spv::StorageClass::StorageBuffer ||
|
||||
storage_class == spv::StorageClass::Uniform) {
|
||||
Instruction* var_type = context()->get_def_use_mgr()->GetDef(type_id());
|
||||
return var_type != nullptr && var_type->IsVulkanStorageBuffer();
|
||||
}
|
||||
@@ -418,13 +431,13 @@ bool Instruction::IsVulkanStorageBufferVariable() const {
|
||||
}
|
||||
|
||||
bool Instruction::IsVulkanUniformBuffer() const {
|
||||
if (opcode() != SpvOpTypePointer) {
|
||||
if (opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class =
|
||||
GetSingleWordInOperand(kPointerTypeStorageClassIndex);
|
||||
if (storage_class != SpvStorageClassUniform) {
|
||||
spv::StorageClass storage_class =
|
||||
spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
|
||||
if (storage_class != spv::StorageClass::Uniform) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -432,19 +445,19 @@ bool Instruction::IsVulkanUniformBuffer() const {
|
||||
context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
|
||||
|
||||
// Unpack the optional layer of arraying.
|
||||
if (base_type->opcode() == SpvOpTypeArray ||
|
||||
base_type->opcode() == SpvOpTypeRuntimeArray) {
|
||||
if (base_type->opcode() == spv::Op::OpTypeArray ||
|
||||
base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
|
||||
base_type = context()->get_def_use_mgr()->GetDef(
|
||||
base_type->GetSingleWordInOperand(0));
|
||||
}
|
||||
|
||||
if (base_type->opcode() != SpvOpTypeStruct) {
|
||||
if (base_type->opcode() != spv::Op::OpTypeStruct) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_block = false;
|
||||
context()->get_decoration_mgr()->ForEachDecoration(
|
||||
base_type->result_id(), SpvDecorationBlock,
|
||||
base_type->result_id(), uint32_t(spv::Decoration::Block),
|
||||
[&is_block](const Instruction&) { is_block = true; });
|
||||
return is_block;
|
||||
}
|
||||
@@ -455,27 +468,27 @@ bool Instruction::IsReadOnlyPointerShaders() const {
|
||||
}
|
||||
|
||||
Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
|
||||
if (type_def->opcode() != SpvOpTypePointer) {
|
||||
if (type_def->opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class =
|
||||
type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
|
||||
spv::StorageClass storage_class = spv::StorageClass(
|
||||
type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));
|
||||
|
||||
switch (storage_class) {
|
||||
case SpvStorageClassUniformConstant:
|
||||
case spv::StorageClass::UniformConstant:
|
||||
if (!type_def->IsVulkanStorageImage() &&
|
||||
!type_def->IsVulkanStorageTexelBuffer()) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvStorageClassUniform:
|
||||
case spv::StorageClass::Uniform:
|
||||
if (!type_def->IsVulkanStorageBuffer()) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SpvStorageClassPushConstant:
|
||||
case SpvStorageClassInput:
|
||||
case spv::StorageClass::PushConstant:
|
||||
case spv::StorageClass::Input:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
@@ -483,7 +496,7 @@ bool Instruction::IsReadOnlyPointerShaders() const {
|
||||
|
||||
bool is_nonwritable = false;
|
||||
context()->get_decoration_mgr()->ForEachDecoration(
|
||||
result_id(), SpvDecorationNonWritable,
|
||||
result_id(), uint32_t(spv::Decoration::NonWritable),
|
||||
[&is_nonwritable](const Instruction&) { is_nonwritable = true; });
|
||||
return is_nonwritable;
|
||||
}
|
||||
@@ -494,14 +507,14 @@ bool Instruction::IsReadOnlyPointerKernel() const {
|
||||
}
|
||||
|
||||
Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
|
||||
if (type_def->opcode() != SpvOpTypePointer) {
|
||||
if (type_def->opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t storage_class =
|
||||
type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
|
||||
spv::StorageClass storage_class = spv::StorageClass(
|
||||
type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));
|
||||
|
||||
return storage_class == SpvStorageClassUniformConstant;
|
||||
return storage_class == spv::StorageClass::UniformConstant;
|
||||
}
|
||||
|
||||
void Instruction::UpdateLexicalScope(uint32_t scope) {
|
||||
@@ -564,13 +577,13 @@ bool Instruction::IsDebugLineInst() const {
|
||||
bool Instruction::IsLineInst() const { return IsLine() || IsNoLine(); }
|
||||
|
||||
bool Instruction::IsLine() const {
|
||||
if (opcode() == SpvOpLine) return true;
|
||||
if (opcode() == spv::Op::OpLine) return true;
|
||||
NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
|
||||
return ext_opt == NonSemanticShaderDebugInfo100DebugLine;
|
||||
}
|
||||
|
||||
bool Instruction::IsNoLine() const {
|
||||
if (opcode() == SpvOpNoLine) return true;
|
||||
if (opcode() == spv::Op::OpNoLine) return true;
|
||||
NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
|
||||
return ext_opt == NonSemanticShaderDebugInfo100DebugNoLine;
|
||||
}
|
||||
@@ -597,33 +610,35 @@ bool Instruction::IsValidBasePointer() const {
|
||||
}
|
||||
|
||||
Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
|
||||
if (type->opcode() != SpvOpTypePointer) {
|
||||
if (type->opcode() != spv::Op::OpTypePointer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto feature_mgr = context()->get_feature_mgr();
|
||||
if (feature_mgr->HasCapability(SpvCapabilityAddresses)) {
|
||||
if (feature_mgr->HasCapability(spv::Capability::Addresses)) {
|
||||
// TODO: The rules here could be more restrictive.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (opcode() == SpvOpVariable || opcode() == SpvOpFunctionParameter) {
|
||||
if (opcode() == spv::Op::OpVariable ||
|
||||
opcode() == spv::Op::OpFunctionParameter) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// With variable pointers, there are more valid base pointer objects.
|
||||
// Variable pointers implicitly declares Variable pointers storage buffer.
|
||||
SpvStorageClass storage_class =
|
||||
static_cast<SpvStorageClass>(type->GetSingleWordInOperand(0));
|
||||
if ((feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer) &&
|
||||
storage_class == SpvStorageClassStorageBuffer) ||
|
||||
(feature_mgr->HasCapability(SpvCapabilityVariablePointers) &&
|
||||
storage_class == SpvStorageClassWorkgroup)) {
|
||||
spv::StorageClass storage_class =
|
||||
static_cast<spv::StorageClass>(type->GetSingleWordInOperand(0));
|
||||
if ((feature_mgr->HasCapability(
|
||||
spv::Capability::VariablePointersStorageBuffer) &&
|
||||
storage_class == spv::StorageClass::StorageBuffer) ||
|
||||
(feature_mgr->HasCapability(spv::Capability::VariablePointers) &&
|
||||
storage_class == spv::StorageClass::Workgroup)) {
|
||||
switch (opcode()) {
|
||||
case SpvOpPhi:
|
||||
case SpvOpSelect:
|
||||
case SpvOpFunctionCall:
|
||||
case SpvOpConstantNull:
|
||||
case spv::Op::OpPhi:
|
||||
case spv::Op::OpSelect:
|
||||
case spv::Op::OpFunctionCall:
|
||||
case spv::Op::OpConstantNull:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
@@ -641,7 +656,7 @@ bool Instruction::IsValidBasePointer() const {
|
||||
}
|
||||
|
||||
OpenCLDebugInfo100Instructions Instruction::GetOpenCL100DebugOpcode() const {
|
||||
if (opcode() != SpvOpExtInst) {
|
||||
if (opcode() != spv::Op::OpExtInst) {
|
||||
return OpenCLDebugInfo100InstructionsMax;
|
||||
}
|
||||
|
||||
@@ -660,7 +675,7 @@ OpenCLDebugInfo100Instructions Instruction::GetOpenCL100DebugOpcode() const {
|
||||
|
||||
NonSemanticShaderDebugInfo100Instructions Instruction::GetShader100DebugOpcode()
|
||||
const {
|
||||
if (opcode() != SpvOpExtInst) {
|
||||
if (opcode() != spv::Op::OpExtInst) {
|
||||
return NonSemanticShaderDebugInfo100InstructionsMax;
|
||||
}
|
||||
|
||||
@@ -682,7 +697,7 @@ NonSemanticShaderDebugInfo100Instructions Instruction::GetShader100DebugOpcode()
|
||||
}
|
||||
|
||||
CommonDebugInfoInstructions Instruction::GetCommonDebugOpcode() const {
|
||||
if (opcode() != SpvOpExtInst) {
|
||||
if (opcode() != spv::Op::OpExtInst) {
|
||||
return CommonDebugInfoInstructionsMax;
|
||||
}
|
||||
|
||||
@@ -712,25 +727,25 @@ bool Instruction::IsValidBaseImage() const {
|
||||
}
|
||||
|
||||
Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
|
||||
return (type->opcode() == SpvOpTypeImage ||
|
||||
type->opcode() == SpvOpTypeSampledImage);
|
||||
return (type->opcode() == spv::Op::OpTypeImage ||
|
||||
type->opcode() == spv::Op::OpTypeSampledImage);
|
||||
}
|
||||
|
||||
bool Instruction::IsOpaqueType() const {
|
||||
if (opcode() == SpvOpTypeStruct) {
|
||||
if (opcode() == spv::Op::OpTypeStruct) {
|
||||
bool is_opaque = false;
|
||||
ForEachInOperand([&is_opaque, this](const uint32_t* op_id) {
|
||||
Instruction* type_inst = context()->get_def_use_mgr()->GetDef(*op_id);
|
||||
is_opaque |= type_inst->IsOpaqueType();
|
||||
});
|
||||
return is_opaque;
|
||||
} else if (opcode() == SpvOpTypeArray) {
|
||||
} else if (opcode() == spv::Op::OpTypeArray) {
|
||||
uint32_t sub_type_id = GetSingleWordInOperand(0);
|
||||
Instruction* sub_type_inst =
|
||||
context()->get_def_use_mgr()->GetDef(sub_type_id);
|
||||
return sub_type_inst->IsOpaqueType();
|
||||
} else {
|
||||
return opcode() == SpvOpTypeRuntimeArray ||
|
||||
return opcode() == spv::Op::OpTypeRuntimeArray ||
|
||||
spvOpcodeIsBaseOpaqueType(opcode());
|
||||
}
|
||||
}
|
||||
@@ -765,22 +780,23 @@ bool Instruction::IsFoldableByFoldScalar() const {
|
||||
bool Instruction::IsFloatingPointFoldingAllowed() const {
|
||||
// TODO: Add the rules for kernels. For now it will be pessimistic.
|
||||
// For now, do not support capabilities introduced by SPV_KHR_float_controls.
|
||||
if (!context_->get_feature_mgr()->HasCapability(SpvCapabilityShader) ||
|
||||
context_->get_feature_mgr()->HasCapability(SpvCapabilityDenormPreserve) ||
|
||||
if (!context_->get_feature_mgr()->HasCapability(spv::Capability::Shader) ||
|
||||
context_->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityDenormFlushToZero) ||
|
||||
spv::Capability::DenormPreserve) ||
|
||||
context_->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilitySignedZeroInfNanPreserve) ||
|
||||
spv::Capability::DenormFlushToZero) ||
|
||||
context_->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityRoundingModeRTZ) ||
|
||||
spv::Capability::SignedZeroInfNanPreserve) ||
|
||||
context_->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityRoundingModeRTE)) {
|
||||
spv::Capability::RoundingModeRTZ) ||
|
||||
context_->get_feature_mgr()->HasCapability(
|
||||
spv::Capability::RoundingModeRTE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_nocontract = false;
|
||||
context_->get_decoration_mgr()->WhileEachDecoration(
|
||||
result_id(), SpvDecorationNoContraction,
|
||||
result_id(), uint32_t(spv::Decoration::NoContraction),
|
||||
[&is_nocontract](const Instruction&) {
|
||||
is_nocontract = true;
|
||||
return false;
|
||||
@@ -816,101 +832,101 @@ void Instruction::Dump() const {
|
||||
|
||||
bool Instruction::IsOpcodeCodeMotionSafe() const {
|
||||
switch (opcode_) {
|
||||
case SpvOpNop:
|
||||
case SpvOpUndef:
|
||||
case SpvOpLoad:
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpArrayLength:
|
||||
case SpvOpVectorExtractDynamic:
|
||||
case SpvOpVectorInsertDynamic:
|
||||
case SpvOpVectorShuffle:
|
||||
case SpvOpCompositeConstruct:
|
||||
case SpvOpCompositeExtract:
|
||||
case SpvOpCompositeInsert:
|
||||
case SpvOpCopyObject:
|
||||
case SpvOpTranspose:
|
||||
case SpvOpConvertFToU:
|
||||
case SpvOpConvertFToS:
|
||||
case SpvOpConvertSToF:
|
||||
case SpvOpConvertUToF:
|
||||
case SpvOpUConvert:
|
||||
case SpvOpSConvert:
|
||||
case SpvOpFConvert:
|
||||
case SpvOpQuantizeToF16:
|
||||
case SpvOpBitcast:
|
||||
case SpvOpSNegate:
|
||||
case SpvOpFNegate:
|
||||
case SpvOpIAdd:
|
||||
case SpvOpFAdd:
|
||||
case SpvOpISub:
|
||||
case SpvOpFSub:
|
||||
case SpvOpIMul:
|
||||
case SpvOpFMul:
|
||||
case SpvOpUDiv:
|
||||
case SpvOpSDiv:
|
||||
case SpvOpFDiv:
|
||||
case SpvOpUMod:
|
||||
case SpvOpSRem:
|
||||
case SpvOpSMod:
|
||||
case SpvOpFRem:
|
||||
case SpvOpFMod:
|
||||
case SpvOpVectorTimesScalar:
|
||||
case SpvOpMatrixTimesScalar:
|
||||
case SpvOpVectorTimesMatrix:
|
||||
case SpvOpMatrixTimesVector:
|
||||
case SpvOpMatrixTimesMatrix:
|
||||
case SpvOpOuterProduct:
|
||||
case SpvOpDot:
|
||||
case SpvOpIAddCarry:
|
||||
case SpvOpISubBorrow:
|
||||
case SpvOpUMulExtended:
|
||||
case SpvOpSMulExtended:
|
||||
case SpvOpAny:
|
||||
case SpvOpAll:
|
||||
case SpvOpIsNan:
|
||||
case SpvOpIsInf:
|
||||
case SpvOpLogicalEqual:
|
||||
case SpvOpLogicalNotEqual:
|
||||
case SpvOpLogicalOr:
|
||||
case SpvOpLogicalAnd:
|
||||
case SpvOpLogicalNot:
|
||||
case SpvOpSelect:
|
||||
case SpvOpIEqual:
|
||||
case SpvOpINotEqual:
|
||||
case SpvOpUGreaterThan:
|
||||
case SpvOpSGreaterThan:
|
||||
case SpvOpUGreaterThanEqual:
|
||||
case SpvOpSGreaterThanEqual:
|
||||
case SpvOpULessThan:
|
||||
case SpvOpSLessThan:
|
||||
case SpvOpULessThanEqual:
|
||||
case SpvOpSLessThanEqual:
|
||||
case SpvOpFOrdEqual:
|
||||
case SpvOpFUnordEqual:
|
||||
case SpvOpFOrdNotEqual:
|
||||
case SpvOpFUnordNotEqual:
|
||||
case SpvOpFOrdLessThan:
|
||||
case SpvOpFUnordLessThan:
|
||||
case SpvOpFOrdGreaterThan:
|
||||
case SpvOpFUnordGreaterThan:
|
||||
case SpvOpFOrdLessThanEqual:
|
||||
case SpvOpFUnordLessThanEqual:
|
||||
case SpvOpFOrdGreaterThanEqual:
|
||||
case SpvOpFUnordGreaterThanEqual:
|
||||
case SpvOpShiftRightLogical:
|
||||
case SpvOpShiftRightArithmetic:
|
||||
case SpvOpShiftLeftLogical:
|
||||
case SpvOpBitwiseOr:
|
||||
case SpvOpBitwiseXor:
|
||||
case SpvOpBitwiseAnd:
|
||||
case SpvOpNot:
|
||||
case SpvOpBitFieldInsert:
|
||||
case SpvOpBitFieldSExtract:
|
||||
case SpvOpBitFieldUExtract:
|
||||
case SpvOpBitReverse:
|
||||
case SpvOpBitCount:
|
||||
case SpvOpSizeOf:
|
||||
case spv::Op::OpNop:
|
||||
case spv::Op::OpUndef:
|
||||
case spv::Op::OpLoad:
|
||||
case spv::Op::OpAccessChain:
|
||||
case spv::Op::OpInBoundsAccessChain:
|
||||
case spv::Op::OpArrayLength:
|
||||
case spv::Op::OpVectorExtractDynamic:
|
||||
case spv::Op::OpVectorInsertDynamic:
|
||||
case spv::Op::OpVectorShuffle:
|
||||
case spv::Op::OpCompositeConstruct:
|
||||
case spv::Op::OpCompositeExtract:
|
||||
case spv::Op::OpCompositeInsert:
|
||||
case spv::Op::OpCopyObject:
|
||||
case spv::Op::OpTranspose:
|
||||
case spv::Op::OpConvertFToU:
|
||||
case spv::Op::OpConvertFToS:
|
||||
case spv::Op::OpConvertSToF:
|
||||
case spv::Op::OpConvertUToF:
|
||||
case spv::Op::OpUConvert:
|
||||
case spv::Op::OpSConvert:
|
||||
case spv::Op::OpFConvert:
|
||||
case spv::Op::OpQuantizeToF16:
|
||||
case spv::Op::OpBitcast:
|
||||
case spv::Op::OpSNegate:
|
||||
case spv::Op::OpFNegate:
|
||||
case spv::Op::OpIAdd:
|
||||
case spv::Op::OpFAdd:
|
||||
case spv::Op::OpISub:
|
||||
case spv::Op::OpFSub:
|
||||
case spv::Op::OpIMul:
|
||||
case spv::Op::OpFMul:
|
||||
case spv::Op::OpUDiv:
|
||||
case spv::Op::OpSDiv:
|
||||
case spv::Op::OpFDiv:
|
||||
case spv::Op::OpUMod:
|
||||
case spv::Op::OpSRem:
|
||||
case spv::Op::OpSMod:
|
||||
case spv::Op::OpFRem:
|
||||
case spv::Op::OpFMod:
|
||||
case spv::Op::OpVectorTimesScalar:
|
||||
case spv::Op::OpMatrixTimesScalar:
|
||||
case spv::Op::OpVectorTimesMatrix:
|
||||
case spv::Op::OpMatrixTimesVector:
|
||||
case spv::Op::OpMatrixTimesMatrix:
|
||||
case spv::Op::OpOuterProduct:
|
||||
case spv::Op::OpDot:
|
||||
case spv::Op::OpIAddCarry:
|
||||
case spv::Op::OpISubBorrow:
|
||||
case spv::Op::OpUMulExtended:
|
||||
case spv::Op::OpSMulExtended:
|
||||
case spv::Op::OpAny:
|
||||
case spv::Op::OpAll:
|
||||
case spv::Op::OpIsNan:
|
||||
case spv::Op::OpIsInf:
|
||||
case spv::Op::OpLogicalEqual:
|
||||
case spv::Op::OpLogicalNotEqual:
|
||||
case spv::Op::OpLogicalOr:
|
||||
case spv::Op::OpLogicalAnd:
|
||||
case spv::Op::OpLogicalNot:
|
||||
case spv::Op::OpSelect:
|
||||
case spv::Op::OpIEqual:
|
||||
case spv::Op::OpINotEqual:
|
||||
case spv::Op::OpUGreaterThan:
|
||||
case spv::Op::OpSGreaterThan:
|
||||
case spv::Op::OpUGreaterThanEqual:
|
||||
case spv::Op::OpSGreaterThanEqual:
|
||||
case spv::Op::OpULessThan:
|
||||
case spv::Op::OpSLessThan:
|
||||
case spv::Op::OpULessThanEqual:
|
||||
case spv::Op::OpSLessThanEqual:
|
||||
case spv::Op::OpFOrdEqual:
|
||||
case spv::Op::OpFUnordEqual:
|
||||
case spv::Op::OpFOrdNotEqual:
|
||||
case spv::Op::OpFUnordNotEqual:
|
||||
case spv::Op::OpFOrdLessThan:
|
||||
case spv::Op::OpFUnordLessThan:
|
||||
case spv::Op::OpFOrdGreaterThan:
|
||||
case spv::Op::OpFUnordGreaterThan:
|
||||
case spv::Op::OpFOrdLessThanEqual:
|
||||
case spv::Op::OpFUnordLessThanEqual:
|
||||
case spv::Op::OpFOrdGreaterThanEqual:
|
||||
case spv::Op::OpFUnordGreaterThanEqual:
|
||||
case spv::Op::OpShiftRightLogical:
|
||||
case spv::Op::OpShiftRightArithmetic:
|
||||
case spv::Op::OpShiftLeftLogical:
|
||||
case spv::Op::OpBitwiseOr:
|
||||
case spv::Op::OpBitwiseXor:
|
||||
case spv::Op::OpBitwiseAnd:
|
||||
case spv::Op::OpNot:
|
||||
case spv::Op::OpBitFieldInsert:
|
||||
case spv::Op::OpBitFieldSExtract:
|
||||
case spv::Op::OpBitFieldUExtract:
|
||||
case spv::Op::OpBitReverse:
|
||||
case spv::Op::OpBitCount:
|
||||
case spv::Op::OpSizeOf:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -922,7 +938,7 @@ bool Instruction::IsScalarizable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (opcode() == SpvOpExtInst) {
|
||||
if (opcode() == spv::Op::OpExtInst) {
|
||||
uint32_t instSetId =
|
||||
context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
|
||||
|
||||
@@ -997,16 +1013,16 @@ bool Instruction::IsOpcodeSafeToDelete() const {
|
||||
}
|
||||
|
||||
switch (opcode()) {
|
||||
case SpvOpDPdx:
|
||||
case SpvOpDPdy:
|
||||
case SpvOpFwidth:
|
||||
case SpvOpDPdxFine:
|
||||
case SpvOpDPdyFine:
|
||||
case SpvOpFwidthFine:
|
||||
case SpvOpDPdxCoarse:
|
||||
case SpvOpDPdyCoarse:
|
||||
case SpvOpFwidthCoarse:
|
||||
case SpvOpImageQueryLod:
|
||||
case spv::Op::OpDPdx:
|
||||
case spv::Op::OpDPdy:
|
||||
case spv::Op::OpFwidth:
|
||||
case spv::Op::OpDPdxFine:
|
||||
case spv::Op::OpDPdyFine:
|
||||
case spv::Op::OpFwidthFine:
|
||||
case spv::Op::OpDPdxCoarse:
|
||||
case spv::Op::OpDPdyCoarse:
|
||||
case spv::Op::OpFwidthCoarse:
|
||||
case spv::Op::OpImageQueryLod:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -1015,7 +1031,7 @@ bool Instruction::IsOpcodeSafeToDelete() const {
|
||||
|
||||
bool Instruction::IsNonSemanticInstruction() const {
|
||||
if (!HasResultId()) return false;
|
||||
if (opcode() != SpvOpExtInst) return false;
|
||||
if (opcode() != spv::Op::OpExtInst) return false;
|
||||
|
||||
auto import_inst =
|
||||
context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(0));
|
||||
@@ -1035,7 +1051,7 @@ void DebugScope::ToBinary(uint32_t type_id, uint32_t result_id,
|
||||
num_words = kDebugScopeNumWordsWithoutInlinedAt;
|
||||
}
|
||||
std::vector<uint32_t> operands = {
|
||||
(num_words << 16) | static_cast<uint16_t>(SpvOpExtInst),
|
||||
(num_words << 16) | static_cast<uint16_t>(spv::Op::OpExtInst),
|
||||
type_id,
|
||||
result_id,
|
||||
ext_set,
|
||||
|
||||
32
3rdparty/spirv-tools/source/opt/instruction.h
vendored
32
3rdparty/spirv-tools/source/opt/instruction.h
vendored
@@ -36,8 +36,8 @@
|
||||
#include "source/util/string_utils.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
const uint32_t kNoDebugScope = 0;
|
||||
const uint32_t kNoInlinedAt = 0;
|
||||
constexpr uint32_t kNoDebugScope = 0;
|
||||
constexpr uint32_t kNoInlinedAt = 0;
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -190,7 +190,7 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
Instruction()
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
context_(nullptr),
|
||||
opcode_(SpvOpNop),
|
||||
opcode_(spv::Op::OpNop),
|
||||
has_type_id_(false),
|
||||
has_result_id_(false),
|
||||
unique_id_(0),
|
||||
@@ -200,7 +200,7 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
Instruction(IRContext*);
|
||||
// Creates an instruction with the given opcode |op| and no additional logical
|
||||
// operands.
|
||||
Instruction(IRContext*, SpvOp);
|
||||
Instruction(IRContext*, spv::Op);
|
||||
// Creates an instruction using the given spv_parsed_instruction_t |inst|. All
|
||||
// the data inside |inst| will be copied and owned in this instance. And keep
|
||||
// record of line-related debug instructions |dbg_line| ahead of this
|
||||
@@ -213,7 +213,7 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
|
||||
// Creates an instruction with the given opcode |op|, type id: |ty_id|,
|
||||
// result id: |res_id| and input operands: |in_operands|.
|
||||
Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id,
|
||||
Instruction(IRContext* c, spv::Op op, uint32_t ty_id, uint32_t res_id,
|
||||
const OperandList& in_operands);
|
||||
|
||||
// TODO: I will want to remove these, but will first have to remove the use of
|
||||
@@ -235,12 +235,12 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
|
||||
IRContext* context() const { return context_; }
|
||||
|
||||
SpvOp opcode() const { return opcode_; }
|
||||
spv::Op opcode() const { return opcode_; }
|
||||
// Sets the opcode of this instruction to a specific opcode. Note this may
|
||||
// invalidate the instruction.
|
||||
// TODO(qining): Remove this function when instruction building and insertion
|
||||
// is well implemented.
|
||||
void SetOpcode(SpvOp op) { opcode_ = op; }
|
||||
void SetOpcode(spv::Op op) { opcode_ = op; }
|
||||
uint32_t type_id() const {
|
||||
return has_type_id_ ? GetSingleWordOperand(0) : 0;
|
||||
}
|
||||
@@ -625,7 +625,7 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
bool IsValidBaseImage() const;
|
||||
|
||||
IRContext* context_; // IR Context
|
||||
SpvOp opcode_; // Opcode
|
||||
spv::Op opcode_; // Opcode
|
||||
bool has_type_id_; // True if the instruction has a type id
|
||||
bool has_result_id_; // True if the instruction has a result id
|
||||
uint32_t unique_id_; // Unique instruction id
|
||||
@@ -732,12 +732,12 @@ inline void Instruction::SetResultType(uint32_t ty_id) {
|
||||
}
|
||||
|
||||
inline bool Instruction::IsNop() const {
|
||||
return opcode_ == SpvOpNop && !has_type_id_ && !has_result_id_ &&
|
||||
return opcode_ == spv::Op::OpNop && !has_type_id_ && !has_result_id_ &&
|
||||
operands_.empty();
|
||||
}
|
||||
|
||||
inline void Instruction::ToNop() {
|
||||
opcode_ = SpvOpNop;
|
||||
opcode_ = spv::Op::OpNop;
|
||||
has_type_id_ = false;
|
||||
has_result_id_ = false;
|
||||
operands_.clear();
|
||||
@@ -879,12 +879,12 @@ inline void Instruction::ForEachInOperand(
|
||||
|
||||
inline bool Instruction::HasLabels() const {
|
||||
switch (opcode_) {
|
||||
case SpvOpSelectionMerge:
|
||||
case SpvOpBranch:
|
||||
case SpvOpLoopMerge:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
case SpvOpPhi:
|
||||
case spv::Op::OpSelectionMerge:
|
||||
case spv::Op::OpBranch:
|
||||
case spv::Op::OpLoopMerge:
|
||||
case spv::Op::OpBranchConditional:
|
||||
case spv::Op::OpSwitch:
|
||||
case spv::Op::OpPhi:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
|
||||
305
3rdparty/spirv-tools/source/opt/instrument_pass.cpp
vendored
305
3rdparty/spirv-tools/source/opt/instrument_pass.cpp
vendored
@@ -19,20 +19,15 @@
|
||||
#include "source/cfa.h"
|
||||
#include "source/spirv_constant.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Common Parameter Positions
|
||||
static const int kInstCommonParamInstIdx = 0;
|
||||
static const int kInstCommonParamCnt = 1;
|
||||
|
||||
// Indices of operands in SPIR-V instructions
|
||||
static const int kEntryPointExecutionModelInIdx = 0;
|
||||
static const int kEntryPointFunctionIdInIdx = 1;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
// Common Parameter Positions
|
||||
constexpr int kInstCommonParamInstIdx = 0;
|
||||
constexpr int kInstCommonParamCnt = 1;
|
||||
// Indices of operands in SPIR-V instructions
|
||||
constexpr int kEntryPointFunctionIdInIdx = 1;
|
||||
} // namespace
|
||||
|
||||
void InstrumentPass::MovePreludeCode(
|
||||
BasicBlock::iterator ref_inst_itr,
|
||||
@@ -83,7 +78,7 @@ void InstrumentPass::MovePostludeCode(
|
||||
|
||||
std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) {
|
||||
std::unique_ptr<Instruction> newLabel(
|
||||
new Instruction(context(), SpvOpLabel, 0, label_id, {}));
|
||||
new Instruction(context(), spv::Op::OpLabel, 0, label_id, {}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*newLabel);
|
||||
return newLabel;
|
||||
}
|
||||
@@ -91,7 +86,7 @@ std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) {
|
||||
std::unique_ptr<Instruction> InstrumentPass::NewName(
|
||||
uint32_t id, const std::string& name_str) {
|
||||
std::unique_ptr<Instruction> new_name(new Instruction(
|
||||
context(), SpvOpName, 0, 0,
|
||||
context(), spv::Op::OpName, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {id}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
|
||||
@@ -124,7 +119,7 @@ std::unique_ptr<Instruction> InstrumentPass::NewGlobalName(
|
||||
std::unique_ptr<Instruction> InstrumentPass::NewMemberName(
|
||||
uint32_t id, uint32_t member_index, const std::string& name_str) {
|
||||
std::unique_ptr<Instruction> new_name(new Instruction(
|
||||
context(), SpvOpMemberName, 0, 0,
|
||||
context(), spv::Op::OpMemberName, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {id}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index}},
|
||||
@@ -145,10 +140,10 @@ uint32_t InstrumentPass::Gen32BitCvtCode(uint32_t val_id,
|
||||
analysis::Type* val_32b_reg_ty = type_mgr->GetRegisteredType(&val_32b_ty);
|
||||
uint32_t val_32b_reg_ty_id = type_mgr->GetId(val_32b_reg_ty);
|
||||
if (is_signed)
|
||||
return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpSConvert, val_id)
|
||||
return builder->AddUnaryOp(val_32b_reg_ty_id, spv::Op::OpSConvert, val_id)
|
||||
->result_id();
|
||||
else
|
||||
return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpUConvert, val_id)
|
||||
return builder->AddUnaryOp(val_32b_reg_ty_id, spv::Op::OpUConvert, val_id)
|
||||
->result_id();
|
||||
}
|
||||
|
||||
@@ -161,7 +156,7 @@ uint32_t InstrumentPass::GenUintCastCode(uint32_t val_id,
|
||||
uint32_t val_ty_id = get_def_use_mgr()->GetDef(val_32b_id)->type_id();
|
||||
analysis::Integer* val_ty = type_mgr->GetType(val_ty_id)->AsInteger();
|
||||
if (!val_ty->IsSigned()) return val_32b_id;
|
||||
return builder->AddUnaryOp(GetUintId(), SpvOpBitcast, val_32b_id)
|
||||
return builder->AddUnaryOp(GetUintId(), spv::Op::OpBitcast, val_32b_id)
|
||||
->result_id();
|
||||
}
|
||||
|
||||
@@ -173,15 +168,16 @@ void InstrumentPass::GenDebugOutputFieldCode(uint32_t base_offset_id,
|
||||
uint32_t val_id = GenUintCastCode(field_value_id, builder);
|
||||
// Store value
|
||||
Instruction* data_idx_inst =
|
||||
builder->AddBinaryOp(GetUintId(), SpvOpIAdd, base_offset_id,
|
||||
builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, base_offset_id,
|
||||
builder->GetUintConstantId(field_offset));
|
||||
uint32_t buf_id = GetOutputBufferId();
|
||||
uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
|
||||
Instruction* achain_inst =
|
||||
builder->AddTernaryOp(buf_uint_ptr_id, SpvOpAccessChain, buf_id,
|
||||
builder->AddTernaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
|
||||
builder->GetUintConstantId(kDebugOutputDataOffset),
|
||||
data_idx_inst->result_id());
|
||||
(void)builder->AddBinaryOp(0, SpvOpStore, achain_inst->result_id(), val_id);
|
||||
(void)builder->AddBinaryOp(0, spv::Op::OpStore, achain_inst->result_id(),
|
||||
val_id);
|
||||
}
|
||||
|
||||
void InstrumentPass::GenCommonStreamWriteCode(uint32_t record_sz,
|
||||
@@ -207,7 +203,7 @@ void InstrumentPass::GenFragCoordEltDebugOutputCode(
|
||||
uint32_t base_offset_id, uint32_t uint_frag_coord_id, uint32_t element,
|
||||
InstructionBuilder* builder) {
|
||||
Instruction* element_val_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, uint_frag_coord_id, element);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, uint_frag_coord_id, element);
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstFragOutFragCoordX + element,
|
||||
element_val_inst->result_id(), builder);
|
||||
}
|
||||
@@ -216,7 +212,8 @@ uint32_t InstrumentPass::GenVarLoad(uint32_t var_id,
|
||||
InstructionBuilder* builder) {
|
||||
Instruction* var_inst = get_def_use_mgr()->GetDef(var_id);
|
||||
uint32_t type_id = GetPointeeTypeId(var_inst);
|
||||
Instruction* load_inst = builder->AddUnaryOp(type_id, SpvOpLoad, var_id);
|
||||
Instruction* load_inst =
|
||||
builder->AddUnaryOp(type_id, spv::Op::OpLoad, var_id);
|
||||
return load_inst->result_id();
|
||||
}
|
||||
|
||||
@@ -233,31 +230,31 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx,
|
||||
uint32_t base_offset_id,
|
||||
InstructionBuilder* builder) {
|
||||
// TODO(greg-lunarg): Add support for all stages
|
||||
switch (stage_idx) {
|
||||
case SpvExecutionModelVertex: {
|
||||
switch (spv::ExecutionModel(stage_idx)) {
|
||||
case spv::ExecutionModel::Vertex: {
|
||||
// Load and store VertexId and InstanceId
|
||||
GenBuiltinOutputCode(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInVertexIndex),
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::VertexIndex)),
|
||||
kInstVertOutVertexIndex, base_offset_id, builder);
|
||||
GenBuiltinOutputCode(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInInstanceIndex),
|
||||
kInstVertOutInstanceIndex, base_offset_id, builder);
|
||||
GenBuiltinOutputCode(context()->GetBuiltinInputVarId(
|
||||
uint32_t(spv::BuiltIn::InstanceIndex)),
|
||||
kInstVertOutInstanceIndex, base_offset_id, builder);
|
||||
} break;
|
||||
case SpvExecutionModelGLCompute:
|
||||
case SpvExecutionModelTaskNV:
|
||||
case SpvExecutionModelMeshNV:
|
||||
case SpvExecutionModelTaskEXT:
|
||||
case SpvExecutionModelMeshEXT: {
|
||||
case spv::ExecutionModel::GLCompute:
|
||||
case spv::ExecutionModel::TaskNV:
|
||||
case spv::ExecutionModel::MeshNV:
|
||||
case spv::ExecutionModel::TaskEXT:
|
||||
case spv::ExecutionModel::MeshEXT: {
|
||||
// Load and store GlobalInvocationId.
|
||||
uint32_t load_id = GenVarLoad(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInGlobalInvocationId),
|
||||
builder);
|
||||
uint32_t load_id = GenVarLoad(context()->GetBuiltinInputVarId(uint32_t(
|
||||
spv::BuiltIn::GlobalInvocationId)),
|
||||
builder);
|
||||
Instruction* x_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, load_id, 0);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, load_id, 0);
|
||||
Instruction* y_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, load_id, 1);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, load_id, 1);
|
||||
Instruction* z_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, load_id, 2);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, load_id, 2);
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdX,
|
||||
x_inst->result_id(), builder);
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdY,
|
||||
@@ -265,69 +262,71 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx,
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdZ,
|
||||
z_inst->result_id(), builder);
|
||||
} break;
|
||||
case SpvExecutionModelGeometry: {
|
||||
case spv::ExecutionModel::Geometry: {
|
||||
// Load and store PrimitiveId and InvocationId.
|
||||
GenBuiltinOutputCode(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
|
||||
kInstGeomOutPrimitiveId, base_offset_id, builder);
|
||||
GenBuiltinOutputCode(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInInvocationId),
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
|
||||
kInstGeomOutInvocationId, base_offset_id, builder);
|
||||
} break;
|
||||
case SpvExecutionModelTessellationControl: {
|
||||
case spv::ExecutionModel::TessellationControl: {
|
||||
// Load and store InvocationId and PrimitiveId
|
||||
GenBuiltinOutputCode(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInInvocationId),
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
|
||||
kInstTessCtlOutInvocationId, base_offset_id, builder);
|
||||
GenBuiltinOutputCode(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
|
||||
kInstTessCtlOutPrimitiveId, base_offset_id, builder);
|
||||
} break;
|
||||
case SpvExecutionModelTessellationEvaluation: {
|
||||
case spv::ExecutionModel::TessellationEvaluation: {
|
||||
// Load and store PrimitiveId and TessCoord.uv
|
||||
GenBuiltinOutputCode(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
|
||||
kInstTessEvalOutPrimitiveId, base_offset_id, builder);
|
||||
uint32_t load_id = GenVarLoad(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInTessCoord), builder);
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::TessCoord)),
|
||||
builder);
|
||||
Instruction* uvec3_cast_inst =
|
||||
builder->AddUnaryOp(GetVec3UintId(), SpvOpBitcast, load_id);
|
||||
builder->AddUnaryOp(GetVec3UintId(), spv::Op::OpBitcast, load_id);
|
||||
uint32_t uvec3_cast_id = uvec3_cast_inst->result_id();
|
||||
Instruction* u_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 0);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 0);
|
||||
Instruction* v_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 1);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 1);
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordU,
|
||||
u_inst->result_id(), builder);
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordV,
|
||||
v_inst->result_id(), builder);
|
||||
} break;
|
||||
case SpvExecutionModelFragment: {
|
||||
case spv::ExecutionModel::Fragment: {
|
||||
// Load FragCoord and convert to Uint
|
||||
Instruction* frag_coord_inst = builder->AddUnaryOp(
|
||||
GetVec4FloatId(), SpvOpLoad,
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInFragCoord));
|
||||
GetVec4FloatId(), spv::Op::OpLoad,
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::FragCoord)));
|
||||
Instruction* uint_frag_coord_inst = builder->AddUnaryOp(
|
||||
GetVec4UintId(), SpvOpBitcast, frag_coord_inst->result_id());
|
||||
GetVec4UintId(), spv::Op::OpBitcast, frag_coord_inst->result_id());
|
||||
for (uint32_t u = 0; u < 2u; ++u)
|
||||
GenFragCoordEltDebugOutputCode(
|
||||
base_offset_id, uint_frag_coord_inst->result_id(), u, builder);
|
||||
} break;
|
||||
case SpvExecutionModelRayGenerationNV:
|
||||
case SpvExecutionModelIntersectionNV:
|
||||
case SpvExecutionModelAnyHitNV:
|
||||
case SpvExecutionModelClosestHitNV:
|
||||
case SpvExecutionModelMissNV:
|
||||
case SpvExecutionModelCallableNV: {
|
||||
case spv::ExecutionModel::RayGenerationNV:
|
||||
case spv::ExecutionModel::IntersectionNV:
|
||||
case spv::ExecutionModel::AnyHitNV:
|
||||
case spv::ExecutionModel::ClosestHitNV:
|
||||
case spv::ExecutionModel::MissNV:
|
||||
case spv::ExecutionModel::CallableNV: {
|
||||
// Load and store LaunchIdNV.
|
||||
uint32_t launch_id = GenVarLoad(
|
||||
context()->GetBuiltinInputVarId(SpvBuiltInLaunchIdNV), builder);
|
||||
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::LaunchIdNV)),
|
||||
builder);
|
||||
Instruction* x_launch_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, launch_id, 0);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, launch_id, 0);
|
||||
Instruction* y_launch_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, launch_id, 1);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, launch_id, 1);
|
||||
Instruction* z_launch_inst = builder->AddIdLiteralOp(
|
||||
GetUintId(), SpvOpCompositeExtract, launch_id, 2);
|
||||
GetUintId(), spv::Op::OpCompositeExtract, launch_id, 2);
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdX,
|
||||
x_launch_inst->result_id(), builder);
|
||||
GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdY,
|
||||
@@ -349,7 +348,7 @@ void InstrumentPass::GenDebugStreamWrite(
|
||||
std::vector<uint32_t> args = {output_func_id,
|
||||
builder->GetUintConstantId(instruction_idx)};
|
||||
(void)args.insert(args.end(), validation_ids.begin(), validation_ids.end());
|
||||
(void)builder->AddNaryOp(GetVoidId(), SpvOpFunctionCall, args);
|
||||
(void)builder->AddNaryOp(GetVoidId(), spv::Op::OpFunctionCall, args);
|
||||
}
|
||||
|
||||
bool InstrumentPass::AllConstant(const std::vector<uint32_t>& ids) {
|
||||
@@ -385,13 +384,15 @@ uint32_t InstrumentPass::GenDebugDirectRead(
|
||||
builder.SetInsertPoint(insert_before);
|
||||
}
|
||||
uint32_t res_id =
|
||||
builder.AddNaryOp(GetUintId(), SpvOpFunctionCall, args)->result_id();
|
||||
builder.AddNaryOp(GetUintId(), spv::Op::OpFunctionCall, args)
|
||||
->result_id();
|
||||
if (insert_in_first_block) call2id_[args] = res_id;
|
||||
return res_id;
|
||||
}
|
||||
|
||||
bool InstrumentPass::IsSameBlockOp(const Instruction* inst) const {
|
||||
return inst->opcode() == SpvOpSampledImage || inst->opcode() == SpvOpImage;
|
||||
return inst->opcode() == spv::Op::OpSampledImage ||
|
||||
inst->opcode() == spv::Op::OpImage;
|
||||
}
|
||||
|
||||
void InstrumentPass::CloneSameBlockOps(
|
||||
@@ -457,7 +458,7 @@ void InstrumentPass::UpdateSucceedingPhis(
|
||||
uint32_t InstrumentPass::GetOutputBufferPtrId() {
|
||||
if (output_buffer_ptr_id_ == 0) {
|
||||
output_buffer_ptr_id_ = context()->get_type_mgr()->FindPointerToType(
|
||||
GetUintId(), SpvStorageClassStorageBuffer);
|
||||
GetUintId(), spv::StorageClass::StorageBuffer);
|
||||
}
|
||||
return output_buffer_ptr_id_;
|
||||
}
|
||||
@@ -470,7 +471,7 @@ uint32_t InstrumentPass::GetInputBufferTypeId() {
|
||||
uint32_t InstrumentPass::GetInputBufferPtrId() {
|
||||
if (input_buffer_ptr_id_ == 0) {
|
||||
input_buffer_ptr_id_ = context()->get_type_mgr()->FindPointerToType(
|
||||
GetInputBufferTypeId(), SpvStorageClassStorageBuffer);
|
||||
GetInputBufferTypeId(), spv::StorageClass::StorageBuffer);
|
||||
}
|
||||
return input_buffer_ptr_id_;
|
||||
}
|
||||
@@ -519,8 +520,8 @@ analysis::Type* InstrumentPass::GetUintXRuntimeArrayType(
|
||||
// invalidated after this pass.
|
||||
assert(context()->get_def_use_mgr()->NumUses(uint_arr_ty_id) == 0 &&
|
||||
"used RuntimeArray type returned");
|
||||
deco_mgr->AddDecorationVal(uint_arr_ty_id, SpvDecorationArrayStride,
|
||||
width / 8u);
|
||||
deco_mgr->AddDecorationVal(
|
||||
uint_arr_ty_id, uint32_t(spv::Decoration::ArrayStride), width / 8u);
|
||||
}
|
||||
return *rarr_ty;
|
||||
}
|
||||
@@ -548,7 +549,7 @@ uint32_t InstrumentPass::GetOutputBufferId() {
|
||||
analysis::Type* reg_uint_rarr_ty = GetUintRuntimeArrayType(32);
|
||||
analysis::Integer uint_ty(32, false);
|
||||
analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
|
||||
analysis::Struct buf_ty({reg_uint_ty, reg_uint_rarr_ty});
|
||||
analysis::Struct buf_ty({reg_uint_ty, reg_uint_ty, reg_uint_rarr_ty});
|
||||
analysis::Type* reg_buf_ty = type_mgr->GetRegisteredType(&buf_ty);
|
||||
uint32_t obufTyId = type_mgr->GetTypeInstruction(reg_buf_ty);
|
||||
// By the Vulkan spec, a pre-existing struct containing a RuntimeArray
|
||||
@@ -559,26 +560,30 @@ uint32_t InstrumentPass::GetOutputBufferId() {
|
||||
// invalidated after this pass.
|
||||
assert(context()->get_def_use_mgr()->NumUses(obufTyId) == 0 &&
|
||||
"used struct type returned");
|
||||
deco_mgr->AddDecoration(obufTyId, SpvDecorationBlock);
|
||||
deco_mgr->AddDecoration(obufTyId, uint32_t(spv::Decoration::Block));
|
||||
deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputFlagsOffset,
|
||||
uint32_t(spv::Decoration::Offset), 0);
|
||||
deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputSizeOffset,
|
||||
SpvDecorationOffset, 0);
|
||||
uint32_t(spv::Decoration::Offset), 4);
|
||||
deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputDataOffset,
|
||||
SpvDecorationOffset, 4);
|
||||
uint32_t(spv::Decoration::Offset), 8);
|
||||
uint32_t obufTyPtrId_ =
|
||||
type_mgr->FindPointerToType(obufTyId, SpvStorageClassStorageBuffer);
|
||||
type_mgr->FindPointerToType(obufTyId, spv::StorageClass::StorageBuffer);
|
||||
output_buffer_id_ = TakeNextId();
|
||||
std::unique_ptr<Instruction> newVarOp(new Instruction(
|
||||
context(), SpvOpVariable, obufTyPtrId_, output_buffer_id_,
|
||||
context(), spv::Op::OpVariable, obufTyPtrId_, output_buffer_id_,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
{SpvStorageClassStorageBuffer}}}));
|
||||
{uint32_t(spv::StorageClass::StorageBuffer)}}}));
|
||||
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(NewMemberName(obufTyId, 0, "flags"));
|
||||
context()->AddDebug2Inst(NewMemberName(obufTyId, 1, "written_count"));
|
||||
context()->AddDebug2Inst(NewMemberName(obufTyId, 2, "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,
|
||||
deco_mgr->AddDecorationVal(
|
||||
output_buffer_id_, uint32_t(spv::Decoration::DescriptorSet), desc_set_);
|
||||
deco_mgr->AddDecorationVal(output_buffer_id_,
|
||||
uint32_t(spv::Decoration::Binding),
|
||||
GetOutputBufferBinding());
|
||||
AddStorageBufferExt();
|
||||
if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
|
||||
@@ -610,22 +615,24 @@ uint32_t InstrumentPass::GetInputBufferId() {
|
||||
// invalidated after this pass.
|
||||
assert(context()->get_def_use_mgr()->NumUses(ibufTyId) == 0 &&
|
||||
"used struct type returned");
|
||||
deco_mgr->AddDecoration(ibufTyId, SpvDecorationBlock);
|
||||
deco_mgr->AddMemberDecoration(ibufTyId, 0, SpvDecorationOffset, 0);
|
||||
deco_mgr->AddDecoration(ibufTyId, uint32_t(spv::Decoration::Block));
|
||||
deco_mgr->AddMemberDecoration(ibufTyId, 0,
|
||||
uint32_t(spv::Decoration::Offset), 0);
|
||||
uint32_t ibufTyPtrId_ =
|
||||
type_mgr->FindPointerToType(ibufTyId, SpvStorageClassStorageBuffer);
|
||||
type_mgr->FindPointerToType(ibufTyId, spv::StorageClass::StorageBuffer);
|
||||
input_buffer_id_ = TakeNextId();
|
||||
std::unique_ptr<Instruction> newVarOp(new Instruction(
|
||||
context(), SpvOpVariable, ibufTyPtrId_, input_buffer_id_,
|
||||
context(), spv::Op::OpVariable, ibufTyPtrId_, input_buffer_id_,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
{SpvStorageClassStorageBuffer}}}));
|
||||
{uint32_t(spv::StorageClass::StorageBuffer)}}}));
|
||||
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,
|
||||
deco_mgr->AddDecorationVal(
|
||||
input_buffer_id_, uint32_t(spv::Decoration::DescriptorSet), desc_set_);
|
||||
deco_mgr->AddDecorationVal(input_buffer_id_,
|
||||
uint32_t(spv::Decoration::Binding),
|
||||
GetInputBufferBinding());
|
||||
AddStorageBufferExt();
|
||||
if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
|
||||
@@ -746,10 +753,10 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
|
||||
analysis::Function func_ty(type_mgr->GetType(GetVoidId()), param_types);
|
||||
analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
|
||||
std::unique_ptr<Instruction> func_inst(
|
||||
new Instruction(get_module()->context(), SpvOpFunction, GetVoidId(),
|
||||
param2output_func_id_[param_cnt],
|
||||
new Instruction(get_module()->context(), spv::Op::OpFunction,
|
||||
GetVoidId(), param2output_func_id_[param_cnt],
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
{SpvFunctionControlMaskNone}},
|
||||
{uint32_t(spv::FunctionControlMask::MaskNone)}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
|
||||
{type_mgr->GetTypeInstruction(reg_func_ty)}}}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
|
||||
@@ -761,7 +768,7 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
|
||||
uint32_t pid = TakeNextId();
|
||||
param_vec.push_back(pid);
|
||||
std::unique_ptr<Instruction> param_inst(
|
||||
new Instruction(get_module()->context(), SpvOpFunctionParameter,
|
||||
new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
|
||||
GetUintId(), pid, {}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
|
||||
output_func->AddParameter(std::move(param_inst));
|
||||
@@ -780,37 +787,39 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
|
||||
uint32_t buf_id = GetOutputBufferId();
|
||||
uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
|
||||
Instruction* obuf_curr_sz_ac_inst =
|
||||
builder.AddBinaryOp(buf_uint_ptr_id, SpvOpAccessChain, buf_id,
|
||||
builder.AddBinaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
|
||||
builder.GetUintConstantId(kDebugOutputSizeOffset));
|
||||
// Fetch the current debug buffer written size atomically, adding the
|
||||
// size of the record to be written.
|
||||
uint32_t obuf_record_sz_id = builder.GetUintConstantId(obuf_record_sz);
|
||||
uint32_t mask_none_id = builder.GetUintConstantId(SpvMemoryAccessMaskNone);
|
||||
uint32_t scope_invok_id = builder.GetUintConstantId(SpvScopeInvocation);
|
||||
uint32_t mask_none_id =
|
||||
builder.GetUintConstantId(uint32_t(spv::MemoryAccessMask::MaskNone));
|
||||
uint32_t scope_invok_id =
|
||||
builder.GetUintConstantId(uint32_t(spv::Scope::Invocation));
|
||||
Instruction* obuf_curr_sz_inst = builder.AddQuadOp(
|
||||
GetUintId(), SpvOpAtomicIAdd, obuf_curr_sz_ac_inst->result_id(),
|
||||
GetUintId(), spv::Op::OpAtomicIAdd, obuf_curr_sz_ac_inst->result_id(),
|
||||
scope_invok_id, mask_none_id, obuf_record_sz_id);
|
||||
uint32_t obuf_curr_sz_id = obuf_curr_sz_inst->result_id();
|
||||
// Compute new written size
|
||||
Instruction* obuf_new_sz_inst =
|
||||
builder.AddBinaryOp(GetUintId(), SpvOpIAdd, obuf_curr_sz_id,
|
||||
builder.AddBinaryOp(GetUintId(), spv::Op::OpIAdd, obuf_curr_sz_id,
|
||||
builder.GetUintConstantId(obuf_record_sz));
|
||||
// Fetch the data bound
|
||||
Instruction* obuf_bnd_inst =
|
||||
builder.AddIdLiteralOp(GetUintId(), SpvOpArrayLength,
|
||||
builder.AddIdLiteralOp(GetUintId(), spv::Op::OpArrayLength,
|
||||
GetOutputBufferId(), kDebugOutputDataOffset);
|
||||
// Test that new written size is less than or equal to debug output
|
||||
// data bound
|
||||
Instruction* obuf_safe_inst = builder.AddBinaryOp(
|
||||
GetBoolId(), SpvOpULessThanEqual, obuf_new_sz_inst->result_id(),
|
||||
GetBoolId(), spv::Op::OpULessThanEqual, obuf_new_sz_inst->result_id(),
|
||||
obuf_bnd_inst->result_id());
|
||||
uint32_t merge_blk_id = TakeNextId();
|
||||
uint32_t write_blk_id = TakeNextId();
|
||||
std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
|
||||
std::unique_ptr<Instruction> write_label(NewLabel(write_blk_id));
|
||||
(void)builder.AddConditionalBranch(obuf_safe_inst->result_id(),
|
||||
write_blk_id, merge_blk_id, merge_blk_id,
|
||||
SpvSelectionControlMaskNone);
|
||||
(void)builder.AddConditionalBranch(
|
||||
obuf_safe_inst->result_id(), write_blk_id, merge_blk_id, merge_blk_id,
|
||||
uint32_t(spv::SelectionControlMask::MaskNone));
|
||||
// Close safety test block and gen write block
|
||||
output_func->AddBasicBlock(std::move(new_blk_ptr));
|
||||
new_blk_ptr = MakeUnique<BasicBlock>(std::move(write_label));
|
||||
@@ -830,10 +839,10 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
|
||||
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
|
||||
builder.SetInsertPoint(&*new_blk_ptr);
|
||||
// Close merge block and function and add function to module
|
||||
(void)builder.AddNullaryOp(0, SpvOpReturn);
|
||||
(void)builder.AddNullaryOp(0, spv::Op::OpReturn);
|
||||
output_func->AddBasicBlock(std::move(new_blk_ptr));
|
||||
std::unique_ptr<Instruction> func_end_inst(
|
||||
new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
|
||||
std::unique_ptr<Instruction> func_end_inst(new Instruction(
|
||||
get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
|
||||
output_func->SetFunctionEnd(std::move(func_end_inst));
|
||||
context()->AddFunction(std::move(output_func));
|
||||
@@ -860,9 +869,9 @@ uint32_t InstrumentPass::GetDirectReadFunctionId(uint32_t param_cnt) {
|
||||
analysis::Function func_ty(type_mgr->GetType(ibuf_type_id), param_types);
|
||||
analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
|
||||
std::unique_ptr<Instruction> func_inst(new Instruction(
|
||||
get_module()->context(), SpvOpFunction, ibuf_type_id, func_id,
|
||||
get_module()->context(), spv::Op::OpFunction, ibuf_type_id, func_id,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
{SpvFunctionControlMaskNone}},
|
||||
{uint32_t(spv::FunctionControlMask::MaskNone)}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
|
||||
{type_mgr->GetTypeInstruction(reg_func_ty)}}}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
|
||||
@@ -873,8 +882,9 @@ uint32_t InstrumentPass::GetDirectReadFunctionId(uint32_t param_cnt) {
|
||||
for (uint32_t c = 0; c < param_cnt; ++c) {
|
||||
uint32_t pid = TakeNextId();
|
||||
param_vec.push_back(pid);
|
||||
std::unique_ptr<Instruction> param_inst(new Instruction(
|
||||
get_module()->context(), SpvOpFunctionParameter, GetUintId(), pid, {}));
|
||||
std::unique_ptr<Instruction> param_inst(
|
||||
new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
|
||||
GetUintId(), pid, {}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
|
||||
input_func->AddParameter(std::move(param_inst));
|
||||
}
|
||||
@@ -899,27 +909,27 @@ uint32_t InstrumentPass::GetDirectReadFunctionId(uint32_t param_cnt) {
|
||||
} else {
|
||||
if (ibuf_type_id != GetUintId()) {
|
||||
Instruction* ucvt_inst =
|
||||
builder.AddUnaryOp(GetUintId(), SpvOpUConvert, last_value_id);
|
||||
builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, last_value_id);
|
||||
last_value_id = ucvt_inst->result_id();
|
||||
}
|
||||
Instruction* offset_inst = builder.AddBinaryOp(
|
||||
GetUintId(), SpvOpIAdd, last_value_id, param_vec[p]);
|
||||
GetUintId(), spv::Op::OpIAdd, last_value_id, param_vec[p]);
|
||||
offset_id = offset_inst->result_id();
|
||||
}
|
||||
Instruction* ac_inst = builder.AddTernaryOp(
|
||||
buf_ptr_id, SpvOpAccessChain, buf_id,
|
||||
buf_ptr_id, spv::Op::OpAccessChain, buf_id,
|
||||
builder.GetUintConstantId(kDebugInputDataOffset), offset_id);
|
||||
Instruction* load_inst =
|
||||
builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, ac_inst->result_id());
|
||||
builder.AddUnaryOp(ibuf_type_id, spv::Op::OpLoad, ac_inst->result_id());
|
||||
last_value_id = load_inst->result_id();
|
||||
}
|
||||
(void)builder.AddInstruction(MakeUnique<Instruction>(
|
||||
context(), SpvOpReturnValue, 0, 0,
|
||||
context(), spv::Op::OpReturnValue, 0, 0,
|
||||
std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {last_value_id}}}));
|
||||
// Close block and function and add function to module
|
||||
input_func->AddBasicBlock(std::move(new_blk_ptr));
|
||||
std::unique_ptr<Instruction> func_end_inst(
|
||||
new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
|
||||
std::unique_ptr<Instruction> func_end_inst(new Instruction(
|
||||
get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
|
||||
input_func->SetFunctionEnd(std::move(func_end_inst));
|
||||
context()->AddFunction(std::move(input_func));
|
||||
@@ -970,7 +980,7 @@ bool InstrumentPass::InstrumentFunction(Function* func, uint32_t stage_idx,
|
||||
// block. This will allow function calls to be inserted into the first
|
||||
// block without interfering with the instrumentation algorithm.
|
||||
if (opt_direct_reads_ && !first_block_split) {
|
||||
if (ii->opcode() != SpvOpVariable) {
|
||||
if (ii->opcode() != spv::Op::OpVariable) {
|
||||
SplitBlock(ii, bi, &new_blks);
|
||||
first_block_split = true;
|
||||
}
|
||||
@@ -1001,7 +1011,9 @@ bool InstrumentPass::InstrumentFunction(Function* func, uint32_t stage_idx,
|
||||
// Restart instrumenting at beginning of last new block,
|
||||
// but skip over any new phi or copy instruction.
|
||||
ii = bi->begin();
|
||||
if (ii->opcode() == SpvOpPhi || ii->opcode() == SpvOpCopyObject) ++ii;
|
||||
if (ii->opcode() == spv::Op::OpPhi ||
|
||||
ii->opcode() == spv::Op::OpCopyObject)
|
||||
++ii;
|
||||
new_blks.clear();
|
||||
}
|
||||
}
|
||||
@@ -1039,35 +1051,24 @@ bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) {
|
||||
// one model per module. In such cases we will need
|
||||
// to clone any functions which are in the call trees of entrypoints
|
||||
// with differing execution models.
|
||||
uint32_t ecnt = 0;
|
||||
uint32_t stage = SpvExecutionModelMax;
|
||||
for (auto& e : get_module()->entry_points()) {
|
||||
if (ecnt == 0)
|
||||
stage = e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx);
|
||||
else if (e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx) !=
|
||||
stage) {
|
||||
if (consumer()) {
|
||||
std::string message = "Mixed stage shader module not supported";
|
||||
consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
++ecnt;
|
||||
}
|
||||
spv::ExecutionModel stage = context()->GetStage();
|
||||
// Check for supported stages
|
||||
if (stage != SpvExecutionModelVertex && stage != SpvExecutionModelFragment &&
|
||||
stage != SpvExecutionModelGeometry &&
|
||||
stage != SpvExecutionModelGLCompute &&
|
||||
stage != SpvExecutionModelTessellationControl &&
|
||||
stage != SpvExecutionModelTessellationEvaluation &&
|
||||
stage != SpvExecutionModelTaskNV && stage != SpvExecutionModelMeshNV &&
|
||||
stage != SpvExecutionModelRayGenerationNV &&
|
||||
stage != SpvExecutionModelIntersectionNV &&
|
||||
stage != SpvExecutionModelAnyHitNV &&
|
||||
stage != SpvExecutionModelClosestHitNV &&
|
||||
stage != SpvExecutionModelMissNV &&
|
||||
stage != SpvExecutionModelCallableNV &&
|
||||
stage != SpvExecutionModelTaskEXT && stage != SpvExecutionModelMeshEXT) {
|
||||
if (stage != spv::ExecutionModel::Vertex &&
|
||||
stage != spv::ExecutionModel::Fragment &&
|
||||
stage != spv::ExecutionModel::Geometry &&
|
||||
stage != spv::ExecutionModel::GLCompute &&
|
||||
stage != spv::ExecutionModel::TessellationControl &&
|
||||
stage != spv::ExecutionModel::TessellationEvaluation &&
|
||||
stage != spv::ExecutionModel::TaskNV &&
|
||||
stage != spv::ExecutionModel::MeshNV &&
|
||||
stage != spv::ExecutionModel::RayGenerationNV &&
|
||||
stage != spv::ExecutionModel::IntersectionNV &&
|
||||
stage != spv::ExecutionModel::AnyHitNV &&
|
||||
stage != spv::ExecutionModel::ClosestHitNV &&
|
||||
stage != spv::ExecutionModel::MissNV &&
|
||||
stage != spv::ExecutionModel::CallableNV &&
|
||||
stage != spv::ExecutionModel::TaskEXT &&
|
||||
stage != spv::ExecutionModel::MeshEXT) {
|
||||
if (consumer()) {
|
||||
std::string message = "Stage not supported by instrumentation";
|
||||
consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
|
||||
@@ -1079,7 +1080,7 @@ bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) {
|
||||
for (auto& e : get_module()->entry_points()) {
|
||||
roots.push(e.GetSingleWordInOperand(kEntryPointFunctionIdInIdx));
|
||||
}
|
||||
bool modified = InstProcessCallTreeFromRoots(pfn, &roots, stage);
|
||||
bool modified = InstProcessCallTreeFromRoots(pfn, &roots, uint32_t(stage));
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,13 +55,14 @@
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
// Validation Ids
|
||||
// These are used to identify the general validation being done and map to
|
||||
// its output buffers.
|
||||
static const uint32_t kInstValidationIdBindless = 0;
|
||||
static const uint32_t kInstValidationIdBuffAddr = 1;
|
||||
static const uint32_t kInstValidationIdDebugPrintf = 2;
|
||||
constexpr uint32_t kInstValidationIdBindless = 0;
|
||||
constexpr uint32_t kInstValidationIdBuffAddr = 1;
|
||||
constexpr uint32_t kInstValidationIdDebugPrintf = 2;
|
||||
} // namespace
|
||||
|
||||
class InstrumentPass : public Pass {
|
||||
using cbb_ptr = const BasicBlock*;
|
||||
|
||||
@@ -23,29 +23,28 @@
|
||||
#include "source/opt/type_manager.h"
|
||||
#include "source/util/make_unique.h"
|
||||
|
||||
const static uint32_t kOpDecorateDecorationInOperandIndex = 1;
|
||||
const static uint32_t kOpDecorateLiteralInOperandIndex = 2;
|
||||
const static uint32_t kOpEntryPointInOperandInterface = 3;
|
||||
const static uint32_t kOpVariableStorageClassInOperandIndex = 0;
|
||||
const static uint32_t kOpTypeArrayElemTypeInOperandIndex = 0;
|
||||
const static uint32_t kOpTypeArrayLengthInOperandIndex = 1;
|
||||
const static uint32_t kOpTypeMatrixColCountInOperandIndex = 1;
|
||||
const static uint32_t kOpTypeMatrixColTypeInOperandIndex = 0;
|
||||
const static uint32_t kOpTypePtrTypeInOperandIndex = 1;
|
||||
const static uint32_t kOpConstantValueInOperandIndex = 0;
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace {
|
||||
constexpr uint32_t kOpDecorateDecorationInOperandIndex = 1;
|
||||
constexpr uint32_t kOpDecorateLiteralInOperandIndex = 2;
|
||||
constexpr uint32_t kOpEntryPointInOperandInterface = 3;
|
||||
constexpr uint32_t kOpVariableStorageClassInOperandIndex = 0;
|
||||
constexpr uint32_t kOpTypeArrayElemTypeInOperandIndex = 0;
|
||||
constexpr uint32_t kOpTypeArrayLengthInOperandIndex = 1;
|
||||
constexpr uint32_t kOpTypeMatrixColCountInOperandIndex = 1;
|
||||
constexpr uint32_t kOpTypeMatrixColTypeInOperandIndex = 0;
|
||||
constexpr uint32_t kOpTypePtrTypeInOperandIndex = 1;
|
||||
constexpr uint32_t kOpConstantValueInOperandIndex = 0;
|
||||
|
||||
// Get the length of the OpTypeArray |array_type|.
|
||||
uint32_t GetArrayLength(analysis::DefUseManager* def_use_mgr,
|
||||
Instruction* array_type) {
|
||||
assert(array_type->opcode() == SpvOpTypeArray);
|
||||
assert(array_type->opcode() == spv::Op::OpTypeArray);
|
||||
uint32_t const_int_id =
|
||||
array_type->GetSingleWordInOperand(kOpTypeArrayLengthInOperandIndex);
|
||||
Instruction* array_length_inst = def_use_mgr->GetDef(const_int_id);
|
||||
assert(array_length_inst->opcode() == SpvOpConstant);
|
||||
assert(array_length_inst->opcode() == spv::Op::OpConstant);
|
||||
return array_length_inst->GetSingleWordInOperand(
|
||||
kOpConstantValueInOperandIndex);
|
||||
}
|
||||
@@ -53,7 +52,7 @@ uint32_t GetArrayLength(analysis::DefUseManager* def_use_mgr,
|
||||
// Get the element type instruction of the OpTypeArray |array_type|.
|
||||
Instruction* GetArrayElementType(analysis::DefUseManager* def_use_mgr,
|
||||
Instruction* array_type) {
|
||||
assert(array_type->opcode() == SpvOpTypeArray);
|
||||
assert(array_type->opcode() == spv::Op::OpTypeArray);
|
||||
uint32_t elem_type_id =
|
||||
array_type->GetSingleWordInOperand(kOpTypeArrayElemTypeInOperandIndex);
|
||||
return def_use_mgr->GetDef(elem_type_id);
|
||||
@@ -62,7 +61,7 @@ Instruction* GetArrayElementType(analysis::DefUseManager* def_use_mgr,
|
||||
// Get the column type instruction of the OpTypeMatrix |matrix_type|.
|
||||
Instruction* GetMatrixColumnType(analysis::DefUseManager* def_use_mgr,
|
||||
Instruction* matrix_type) {
|
||||
assert(matrix_type->opcode() == SpvOpTypeMatrix);
|
||||
assert(matrix_type->opcode() == spv::Op::OpTypeMatrix);
|
||||
uint32_t column_type_id =
|
||||
matrix_type->GetSingleWordInOperand(kOpTypeMatrixColTypeInOperandIndex);
|
||||
return def_use_mgr->GetDef(column_type_id);
|
||||
@@ -77,14 +76,14 @@ uint32_t GetComponentTypeOfArrayMatrix(analysis::DefUseManager* def_use_mgr,
|
||||
if (depth_to_component == 0) return type_id;
|
||||
|
||||
Instruction* type_inst = def_use_mgr->GetDef(type_id);
|
||||
if (type_inst->opcode() == SpvOpTypeArray) {
|
||||
if (type_inst->opcode() == spv::Op::OpTypeArray) {
|
||||
uint32_t elem_type_id =
|
||||
type_inst->GetSingleWordInOperand(kOpTypeArrayElemTypeInOperandIndex);
|
||||
return GetComponentTypeOfArrayMatrix(def_use_mgr, elem_type_id,
|
||||
depth_to_component - 1);
|
||||
}
|
||||
|
||||
assert(type_inst->opcode() == SpvOpTypeMatrix);
|
||||
assert(type_inst->opcode() == spv::Op::OpTypeMatrix);
|
||||
uint32_t column_type_id =
|
||||
type_inst->GetSingleWordInOperand(kOpTypeMatrixColTypeInOperandIndex);
|
||||
return GetComponentTypeOfArrayMatrix(def_use_mgr, column_type_id,
|
||||
@@ -94,7 +93,7 @@ uint32_t GetComponentTypeOfArrayMatrix(analysis::DefUseManager* def_use_mgr,
|
||||
// Creates an OpDecorate instruction whose Target is |var_id| and Decoration is
|
||||
// |decoration|. Adds |literal| as an extra operand of the instruction.
|
||||
void CreateDecoration(analysis::DecorationManager* decoration_mgr,
|
||||
uint32_t var_id, SpvDecoration decoration,
|
||||
uint32_t var_id, spv::Decoration decoration,
|
||||
uint32_t literal) {
|
||||
std::vector<Operand> operands({
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {var_id}},
|
||||
@@ -102,7 +101,7 @@ void CreateDecoration(analysis::DecorationManager* decoration_mgr,
|
||||
{static_cast<uint32_t>(decoration)}},
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {literal}},
|
||||
});
|
||||
decoration_mgr->AddDecoration(SpvOpDecorate, std::move(operands));
|
||||
decoration_mgr->AddDecoration(spv::Op::OpDecorate, std::move(operands));
|
||||
}
|
||||
|
||||
// Replaces load instructions with composite construct instructions in all the
|
||||
@@ -128,8 +127,8 @@ void ReplaceLoadWithCompositeConstruct(
|
||||
}
|
||||
|
||||
// Returns the storage class of the instruction |var|.
|
||||
SpvStorageClass GetStorageClass(Instruction* var) {
|
||||
return static_cast<SpvStorageClass>(
|
||||
spv::StorageClass GetStorageClass(Instruction* var) {
|
||||
return static_cast<spv::StorageClass>(
|
||||
var->GetSingleWordInOperand(kOpVariableStorageClassInOperandIndex));
|
||||
}
|
||||
|
||||
@@ -137,16 +136,17 @@ SpvStorageClass GetStorageClass(Instruction* var) {
|
||||
|
||||
bool InterfaceVariableScalarReplacement::HasExtraArrayness(
|
||||
Instruction& entry_point, Instruction* var) {
|
||||
SpvExecutionModel execution_model =
|
||||
static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
|
||||
if (execution_model != SpvExecutionModelTessellationEvaluation &&
|
||||
execution_model != SpvExecutionModelTessellationControl) {
|
||||
spv::ExecutionModel execution_model =
|
||||
static_cast<spv::ExecutionModel>(entry_point.GetSingleWordInOperand(0));
|
||||
if (execution_model != spv::ExecutionModel::TessellationEvaluation &&
|
||||
execution_model != spv::ExecutionModel::TessellationControl) {
|
||||
return false;
|
||||
}
|
||||
if (!context()->get_decoration_mgr()->HasDecoration(var->result_id(),
|
||||
SpvDecorationPatch)) {
|
||||
if (execution_model == SpvExecutionModelTessellationControl) return true;
|
||||
return GetStorageClass(var) != SpvStorageClassOutput;
|
||||
if (!context()->get_decoration_mgr()->HasDecoration(
|
||||
var->result_id(), uint32_t(spv::Decoration::Patch))) {
|
||||
if (execution_model == spv::ExecutionModel::TessellationControl)
|
||||
return true;
|
||||
return GetStorageClass(var) != spv::StorageClass::Output;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ bool InterfaceVariableScalarReplacement::
|
||||
bool InterfaceVariableScalarReplacement::GetVariableLocation(
|
||||
Instruction* var, uint32_t* location) {
|
||||
return !context()->get_decoration_mgr()->WhileEachDecoration(
|
||||
var->result_id(), SpvDecorationLocation,
|
||||
var->result_id(), uint32_t(spv::Decoration::Location),
|
||||
[location](const Instruction& inst) {
|
||||
*location =
|
||||
inst.GetSingleWordInOperand(kOpDecorateLiteralInOperandIndex);
|
||||
@@ -174,7 +174,7 @@ bool InterfaceVariableScalarReplacement::GetVariableLocation(
|
||||
bool InterfaceVariableScalarReplacement::GetVariableComponent(
|
||||
Instruction* var, uint32_t* component) {
|
||||
return !context()->get_decoration_mgr()->WhileEachDecoration(
|
||||
var->result_id(), SpvDecorationComponent,
|
||||
var->result_id(), uint32_t(spv::Decoration::Component),
|
||||
[component](const Instruction& inst) {
|
||||
*component =
|
||||
inst.GetSingleWordInOperand(kOpDecorateLiteralInOperandIndex);
|
||||
@@ -190,11 +190,11 @@ InterfaceVariableScalarReplacement::CollectInterfaceVariables(
|
||||
i < entry_point.NumInOperands(); ++i) {
|
||||
Instruction* interface_var = context()->get_def_use_mgr()->GetDef(
|
||||
entry_point.GetSingleWordInOperand(i));
|
||||
assert(interface_var->opcode() == SpvOpVariable);
|
||||
assert(interface_var->opcode() == spv::Op::OpVariable);
|
||||
|
||||
SpvStorageClass storage_class = GetStorageClass(interface_var);
|
||||
if (storage_class != SpvStorageClassInput &&
|
||||
storage_class != SpvStorageClassOutput) {
|
||||
spv::StorageClass storage_class = GetStorageClass(interface_var);
|
||||
if (storage_class != spv::StorageClass::Input &&
|
||||
storage_class != spv::StorageClass::Output) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -205,10 +205,10 @@ InterfaceVariableScalarReplacement::CollectInterfaceVariables(
|
||||
|
||||
void InterfaceVariableScalarReplacement::KillInstructionAndUsers(
|
||||
Instruction* inst) {
|
||||
if (inst->opcode() == SpvOpEntryPoint) {
|
||||
if (inst->opcode() == spv::Op::OpEntryPoint) {
|
||||
return;
|
||||
}
|
||||
if (inst->opcode() != SpvOpAccessChain) {
|
||||
if (inst->opcode() != spv::Op::OpAccessChain) {
|
||||
context()->KillInst(inst);
|
||||
return;
|
||||
}
|
||||
@@ -232,10 +232,10 @@ void InterfaceVariableScalarReplacement::KillLocationAndComponentDecorations(
|
||||
uint32_t var_id) {
|
||||
context()->get_decoration_mgr()->RemoveDecorationsFrom(
|
||||
var_id, [](const Instruction& inst) {
|
||||
uint32_t decoration =
|
||||
inst.GetSingleWordInOperand(kOpDecorateDecorationInOperandIndex);
|
||||
return decoration == SpvDecorationLocation ||
|
||||
decoration == SpvDecorationComponent;
|
||||
spv::Decoration decoration = spv::Decoration(
|
||||
inst.GetSingleWordInOperand(kOpDecorateDecorationInOperandIndex));
|
||||
return decoration == spv::Decoration::Location ||
|
||||
decoration == spv::Decoration::Component;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -307,9 +307,9 @@ void InterfaceVariableScalarReplacement::AddLocationAndComponentDecorations(
|
||||
if (!vars.HasMultipleComponents()) {
|
||||
uint32_t var_id = vars.GetComponentVariable()->result_id();
|
||||
CreateDecoration(context()->get_decoration_mgr(), var_id,
|
||||
SpvDecorationLocation, *location);
|
||||
spv::Decoration::Location, *location);
|
||||
CreateDecoration(context()->get_decoration_mgr(), var_id,
|
||||
SpvDecorationComponent, component);
|
||||
spv::Decoration::Component, component);
|
||||
++(*location);
|
||||
return;
|
||||
}
|
||||
@@ -389,15 +389,15 @@ bool InterfaceVariableScalarReplacement::ReplaceComponentOfInterfaceVarWith(
|
||||
std::unordered_map<Instruction*, Instruction*>* loads_to_component_values,
|
||||
std::unordered_map<Instruction*, Instruction*>*
|
||||
loads_for_access_chain_to_component_values) {
|
||||
SpvOp opcode = interface_var_user->opcode();
|
||||
if (opcode == SpvOpStore) {
|
||||
spv::Op opcode = interface_var_user->opcode();
|
||||
if (opcode == spv::Op::OpStore) {
|
||||
uint32_t value_id = interface_var_user->GetSingleWordInOperand(1);
|
||||
StoreComponentOfValueToScalarVar(value_id, interface_var_component_indices,
|
||||
scalar_var, extra_array_index,
|
||||
interface_var_user);
|
||||
return true;
|
||||
}
|
||||
if (opcode == SpvOpLoad) {
|
||||
if (opcode == spv::Op::OpLoad) {
|
||||
Instruction* scalar_load =
|
||||
LoadScalarVar(scalar_var, extra_array_index, interface_var_user);
|
||||
loads_to_component_values->insert({interface_var_user, scalar_load});
|
||||
@@ -408,25 +408,25 @@ bool InterfaceVariableScalarReplacement::ReplaceComponentOfInterfaceVarWith(
|
||||
// them only for the first element of the extra array.
|
||||
if (extra_array_index && *extra_array_index != 0) return true;
|
||||
|
||||
if (opcode == SpvOpDecorateId || opcode == SpvOpDecorateString ||
|
||||
opcode == SpvOpDecorate) {
|
||||
if (opcode == spv::Op::OpDecorateId || opcode == spv::Op::OpDecorateString ||
|
||||
opcode == spv::Op::OpDecorate) {
|
||||
CloneAnnotationForVariable(interface_var_user, scalar_var->result_id());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (opcode == SpvOpName) {
|
||||
if (opcode == spv::Op::OpName) {
|
||||
std::unique_ptr<Instruction> new_inst(interface_var_user->Clone(context()));
|
||||
new_inst->SetInOperand(0, {scalar_var->result_id()});
|
||||
context()->AddDebug2Inst(std::move(new_inst));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (opcode == SpvOpEntryPoint) {
|
||||
if (opcode == spv::Op::OpEntryPoint) {
|
||||
return ReplaceInterfaceVarInEntryPoint(interface_var, interface_var_user,
|
||||
scalar_var->result_id());
|
||||
}
|
||||
|
||||
if (opcode == SpvOpAccessChain) {
|
||||
if (opcode == spv::Op::OpAccessChain) {
|
||||
ReplaceAccessChainWith(interface_var_user, interface_var_component_indices,
|
||||
scalar_var,
|
||||
loads_for_access_chain_to_component_values);
|
||||
@@ -445,8 +445,8 @@ bool InterfaceVariableScalarReplacement::ReplaceComponentOfInterfaceVarWith(
|
||||
|
||||
void InterfaceVariableScalarReplacement::UseBaseAccessChainForAccessChain(
|
||||
Instruction* access_chain, Instruction* base_access_chain) {
|
||||
assert(base_access_chain->opcode() == SpvOpAccessChain &&
|
||||
access_chain->opcode() == SpvOpAccessChain &&
|
||||
assert(base_access_chain->opcode() == spv::Op::OpAccessChain &&
|
||||
access_chain->opcode() == spv::Op::OpAccessChain &&
|
||||
access_chain->GetSingleWordInOperand(0) ==
|
||||
base_access_chain->result_id());
|
||||
Instruction::OperandList new_operands;
|
||||
@@ -470,10 +470,10 @@ Instruction* InterfaceVariableScalarReplacement::CreateAccessChainToVar(
|
||||
uint32_t ptr_type_id =
|
||||
GetPointerType(*component_type_id, GetStorageClass(var));
|
||||
|
||||
std::unique_ptr<Instruction> new_access_chain(
|
||||
new Instruction(context(), SpvOpAccessChain, ptr_type_id, TakeNextId(),
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
|
||||
std::unique_ptr<Instruction> new_access_chain(new Instruction(
|
||||
context(), spv::Op::OpAccessChain, ptr_type_id, TakeNextId(),
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
|
||||
for (uint32_t index_id : index_ids) {
|
||||
new_access_chain->AddOperand({SPV_OPERAND_TYPE_ID, {index_id}});
|
||||
}
|
||||
@@ -489,13 +489,13 @@ Instruction* InterfaceVariableScalarReplacement::CreateAccessChainWithIndex(
|
||||
Instruction* insert_before) {
|
||||
uint32_t ptr_type_id =
|
||||
GetPointerType(component_type_id, GetStorageClass(var));
|
||||
uint32_t index_id = context()->get_constant_mgr()->GetUIntConst(index);
|
||||
std::unique_ptr<Instruction> new_access_chain(
|
||||
new Instruction(context(), SpvOpAccessChain, ptr_type_id, TakeNextId(),
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {var->result_id()}},
|
||||
{SPV_OPERAND_TYPE_ID, {index_id}},
|
||||
}));
|
||||
uint32_t index_id = context()->get_constant_mgr()->GetUIntConstId(index);
|
||||
std::unique_ptr<Instruction> new_access_chain(new Instruction(
|
||||
context(), spv::Op::OpAccessChain, ptr_type_id, TakeNextId(),
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {var->result_id()}},
|
||||
{SPV_OPERAND_TYPE_ID, {index_id}},
|
||||
}));
|
||||
Instruction* inst = new_access_chain.get();
|
||||
context()->get_def_use_mgr()->AnalyzeInstDefUse(inst);
|
||||
insert_before->InsertBefore(std::move(new_access_chain));
|
||||
@@ -519,20 +519,20 @@ void InterfaceVariableScalarReplacement::ReplaceAccessChainWith(
|
||||
[this, access_chain, &indexes, &interface_var_component_indices,
|
||||
scalar_var, loads_to_component_values](Instruction* user) {
|
||||
switch (user->opcode()) {
|
||||
case SpvOpAccessChain: {
|
||||
case spv::Op::OpAccessChain: {
|
||||
UseBaseAccessChainForAccessChain(user, access_chain);
|
||||
ReplaceAccessChainWith(user, interface_var_component_indices,
|
||||
scalar_var, loads_to_component_values);
|
||||
return;
|
||||
}
|
||||
case SpvOpStore: {
|
||||
case spv::Op::OpStore: {
|
||||
uint32_t value_id = user->GetSingleWordInOperand(1);
|
||||
StoreComponentOfValueToAccessChainToScalarVar(
|
||||
value_id, interface_var_component_indices, scalar_var, indexes,
|
||||
user);
|
||||
return;
|
||||
}
|
||||
case SpvOpLoad: {
|
||||
case spv::Op::OpLoad: {
|
||||
Instruction* value =
|
||||
LoadAccessChainToVar(scalar_var, indexes, user);
|
||||
loads_to_component_values->insert({user, value});
|
||||
@@ -546,9 +546,9 @@ void InterfaceVariableScalarReplacement::ReplaceAccessChainWith(
|
||||
|
||||
void InterfaceVariableScalarReplacement::CloneAnnotationForVariable(
|
||||
Instruction* annotation_inst, uint32_t var_id) {
|
||||
assert(annotation_inst->opcode() == SpvOpDecorate ||
|
||||
annotation_inst->opcode() == SpvOpDecorateId ||
|
||||
annotation_inst->opcode() == SpvOpDecorateString);
|
||||
assert(annotation_inst->opcode() == spv::Op::OpDecorate ||
|
||||
annotation_inst->opcode() == spv::Op::OpDecorateId ||
|
||||
annotation_inst->opcode() == spv::Op::OpDecorateString);
|
||||
std::unique_ptr<Instruction> new_inst(annotation_inst->Clone(context()));
|
||||
new_inst->SetInOperand(0, {var_id});
|
||||
context()->AddAnnotationInst(std::move(new_inst));
|
||||
@@ -593,13 +593,13 @@ bool InterfaceVariableScalarReplacement::ReplaceInterfaceVarInEntryPoint(
|
||||
|
||||
uint32_t InterfaceVariableScalarReplacement::GetPointeeTypeIdOfVar(
|
||||
Instruction* var) {
|
||||
assert(var->opcode() == SpvOpVariable);
|
||||
assert(var->opcode() == spv::Op::OpVariable);
|
||||
|
||||
uint32_t ptr_type_id = var->type_id();
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
Instruction* ptr_type_inst = def_use_mgr->GetDef(ptr_type_id);
|
||||
|
||||
assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
|
||||
assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
|
||||
"Variable must have a pointer type.");
|
||||
return ptr_type_inst->GetSingleWordInOperand(kOpTypePtrTypeInOperandIndex);
|
||||
}
|
||||
@@ -643,7 +643,7 @@ Instruction* InterfaceVariableScalarReplacement::LoadScalarVar(
|
||||
Instruction* InterfaceVariableScalarReplacement::CreateLoad(
|
||||
uint32_t type_id, Instruction* ptr, Instruction* insert_before) {
|
||||
std::unique_ptr<Instruction> load(
|
||||
new Instruction(context(), SpvOpLoad, type_id, TakeNextId(),
|
||||
new Instruction(context(), spv::Op::OpLoad, type_id, TakeNextId(),
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {ptr->result_id()}}}));
|
||||
Instruction* load_inst = load.get();
|
||||
@@ -660,7 +660,7 @@ void InterfaceVariableScalarReplacement::StoreComponentOfValueTo(
|
||||
component_type_id, value_id, component_indices, extra_array_index));
|
||||
|
||||
std::unique_ptr<Instruction> new_store(
|
||||
new Instruction(context(), SpvOpStore));
|
||||
new Instruction(context(), spv::Op::OpStore));
|
||||
new_store->AddOperand({SPV_OPERAND_TYPE_ID, {ptr->result_id()}});
|
||||
new_store->AddOperand(
|
||||
{SPV_OPERAND_TYPE_ID, {composite_extract->result_id()}});
|
||||
@@ -678,7 +678,7 @@ Instruction* InterfaceVariableScalarReplacement::CreateCompositeExtract(
|
||||
const std::vector<uint32_t>& indexes, const uint32_t* extra_first_index) {
|
||||
uint32_t component_id = TakeNextId();
|
||||
Instruction* composite_extract = new Instruction(
|
||||
context(), SpvOpCompositeExtract, type_id, component_id,
|
||||
context(), spv::Op::OpCompositeExtract, type_id, component_id,
|
||||
std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {composite_id}}});
|
||||
if (extra_first_index) {
|
||||
composite_extract->AddOperand(
|
||||
@@ -731,8 +731,8 @@ InterfaceVariableScalarReplacement::CreateCompositeConstructForComponentOfLoad(
|
||||
depth_to_component);
|
||||
}
|
||||
uint32_t new_id = context()->TakeNextId();
|
||||
std::unique_ptr<Instruction> new_composite_construct(
|
||||
new Instruction(context(), SpvOpCompositeConstruct, type_id, new_id, {}));
|
||||
std::unique_ptr<Instruction> new_composite_construct(new Instruction(
|
||||
context(), spv::Op::OpCompositeConstruct, type_id, new_id, {}));
|
||||
Instruction* composite_construct = new_composite_construct.get();
|
||||
def_use_mgr->AnalyzeInstDefUse(composite_construct);
|
||||
|
||||
@@ -781,7 +781,7 @@ uint32_t InterfaceVariableScalarReplacement::GetArrayType(
|
||||
uint32_t elem_type_id, uint32_t array_length) {
|
||||
analysis::Type* elem_type = context()->get_type_mgr()->GetType(elem_type_id);
|
||||
uint32_t array_length_id =
|
||||
context()->get_constant_mgr()->GetUIntConst(array_length);
|
||||
context()->get_constant_mgr()->GetUIntConstId(array_length);
|
||||
analysis::Array array_type(
|
||||
elem_type,
|
||||
analysis::Array::LengthInfo{array_length_id, {0, array_length}});
|
||||
@@ -789,7 +789,7 @@ uint32_t InterfaceVariableScalarReplacement::GetArrayType(
|
||||
}
|
||||
|
||||
uint32_t InterfaceVariableScalarReplacement::GetPointerType(
|
||||
uint32_t type_id, SpvStorageClass storage_class) {
|
||||
uint32_t type_id, spv::StorageClass storage_class) {
|
||||
analysis::Type* type = context()->get_type_mgr()->GetType(type_id);
|
||||
analysis::Pointer ptr_type(type, storage_class);
|
||||
return context()->get_type_mgr()->GetTypeInstruction(&ptr_type);
|
||||
@@ -797,9 +797,9 @@ uint32_t InterfaceVariableScalarReplacement::GetPointerType(
|
||||
|
||||
InterfaceVariableScalarReplacement::NestedCompositeComponents
|
||||
InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForArray(
|
||||
Instruction* interface_var_type, SpvStorageClass storage_class,
|
||||
Instruction* interface_var_type, spv::StorageClass storage_class,
|
||||
uint32_t extra_array_length) {
|
||||
assert(interface_var_type->opcode() == SpvOpTypeArray);
|
||||
assert(interface_var_type->opcode() == spv::Op::OpTypeArray);
|
||||
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
uint32_t array_length = GetArrayLength(def_use_mgr, interface_var_type);
|
||||
@@ -818,9 +818,9 @@ InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForArray(
|
||||
|
||||
InterfaceVariableScalarReplacement::NestedCompositeComponents
|
||||
InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForMatrix(
|
||||
Instruction* interface_var_type, SpvStorageClass storage_class,
|
||||
Instruction* interface_var_type, spv::StorageClass storage_class,
|
||||
uint32_t extra_array_length) {
|
||||
assert(interface_var_type->opcode() == SpvOpTypeMatrix);
|
||||
assert(interface_var_type->opcode() == spv::Op::OpTypeMatrix);
|
||||
|
||||
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
|
||||
uint32_t column_count = interface_var_type->GetSingleWordInOperand(
|
||||
@@ -841,16 +841,16 @@ InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForMatrix(
|
||||
|
||||
InterfaceVariableScalarReplacement::NestedCompositeComponents
|
||||
InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForReplacement(
|
||||
Instruction* interface_var_type, SpvStorageClass storage_class,
|
||||
Instruction* interface_var_type, spv::StorageClass storage_class,
|
||||
uint32_t extra_array_length) {
|
||||
// Handle array case.
|
||||
if (interface_var_type->opcode() == SpvOpTypeArray) {
|
||||
if (interface_var_type->opcode() == spv::Op::OpTypeArray) {
|
||||
return CreateScalarInterfaceVarsForArray(interface_var_type, storage_class,
|
||||
extra_array_length);
|
||||
}
|
||||
|
||||
// Handle matrix case.
|
||||
if (interface_var_type->opcode() == SpvOpTypeMatrix) {
|
||||
if (interface_var_type->opcode() == spv::Op::OpTypeMatrix) {
|
||||
return CreateScalarInterfaceVarsForMatrix(interface_var_type, storage_class,
|
||||
extra_array_length);
|
||||
}
|
||||
@@ -865,7 +865,7 @@ InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForReplacement(
|
||||
context()->get_type_mgr()->FindPointerToType(type_id, storage_class);
|
||||
uint32_t id = TakeNextId();
|
||||
std::unique_ptr<Instruction> variable(
|
||||
new Instruction(context(), SpvOpVariable, ptr_type_id, id,
|
||||
new Instruction(context(), spv::Op::OpVariable, ptr_type_id, id,
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
{static_cast<uint32_t>(storage_class)}}}));
|
||||
@@ -948,8 +948,8 @@ InterfaceVariableScalarReplacement::ReplaceInterfaceVarsWithScalars(
|
||||
return Pass::Status::Failure;
|
||||
}
|
||||
|
||||
if (interface_var_type->opcode() != SpvOpTypeArray &&
|
||||
interface_var_type->opcode() != SpvOpTypeMatrix) {
|
||||
if (interface_var_type->opcode() != spv::Op::OpTypeArray &&
|
||||
interface_var_type->opcode() != spv::Op::OpTypeMatrix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user