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:
@@ -134,4 +134,4 @@ enum DebugInfoDebugOperation {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SPIRV_EXTINST_DebugInfo_H_
|
||||
#endif // SPIRV_EXTINST_DebugInfo_H_
|
||||
@@ -1 +1 @@
|
||||
"v2019.4-dev", "SPIRV-Tools v2019.4-dev v2019.3-90-g76b75c40"
|
||||
"v2019.4-dev", "SPIRV-Tools v2019.4-dev v2019.3-99-g65f49dfc"
|
||||
|
||||
@@ -32,6 +32,7 @@ static const SpvCapability pygen_variable_caps_PipeStorage[] = {SpvCapabilityPip
|
||||
static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes};
|
||||
static const SpvCapability pygen_variable_caps_RayTracingNV[] = {SpvCapabilityRayTracingNV};
|
||||
static const SpvCapability pygen_variable_caps_Shader[] = {SpvCapabilityShader};
|
||||
static const SpvCapability pygen_variable_caps_ShaderClockKHR[] = {SpvCapabilityShaderClockKHR};
|
||||
static const SpvCapability pygen_variable_caps_SparseResidency[] = {SpvCapabilitySparseResidency};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupAvcMotionEstimationINTEL[] = {SpvCapabilitySubgroupAvcMotionEstimationINTEL};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationChromaINTEL[] = {SpvCapabilitySubgroupAvcMotionEstimationINTEL, SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL};
|
||||
@@ -51,6 +52,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_fragment_shader_int
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_decorate_stringSPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_decorate_string, spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1[] = {spvtools::Extension::kSPV_GOOGLE_hlsl_functionality1};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_vote[] = {spvtools::Extension::kSPV_KHR_subgroup_vote};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_cooperative_matrix[] = {spvtools::Extension::kSPV_NV_cooperative_matrix};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_NV_mesh_shader};
|
||||
@@ -419,6 +421,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"GroupSMaxNonUniformAMD", SpvOpGroupSMaxNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentMaskFetchAMD", SpvOpFragmentMaskFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentFetchAMD", SpvOpFragmentFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu, 0xffffffffu},
|
||||
{"ReadClockKHR", SpvOpReadClockKHR, 1, pygen_variable_caps_ShaderClockKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_clock, 0xffffffffu, 0xffffffffu},
|
||||
{"ImageSampleFootprintNV", SpvOpImageSampleFootprintNV, 1, pygen_variable_caps_ImageFootprintNV, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_image_footprint, 0xffffffffu, 0xffffffffu},
|
||||
{"GroupNonUniformPartitionNV", SpvOpGroupNonUniformPartitionNV, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_subgroup_partitioned, 0xffffffffu, 0xffffffffu},
|
||||
{"WritePackedPrimitiveIndices4x8NV", SpvOpWritePackedPrimitiveIndices4x8NV, 1, pygen_variable_caps_MeshShadingNV, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_NV_mesh_shader, 0xffffffffu, 0xffffffffu},
|
||||
@@ -583,4 +586,4 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"SubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL", SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL, 2, pygen_variable_caps_SubgroupAvcMotionEstimationINTELSubgroupAvcMotionEstimationIntraINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupAvcSicGetInterRawSadsINTEL", SpvOpSubgroupAvcSicGetInterRawSadsINTEL, 1, pygen_variable_caps_SubgroupAvcMotionEstimationINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}
|
||||
};
|
||||
};
|
||||
@@ -35,4 +35,4 @@ static const spv_ext_inst_desc_t debuginfo_entries[] = {
|
||||
{"DebugExpression", 31, 0, nullptr, {SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugMacroDef", 32, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugMacroUndef", 33, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
};
|
||||
@@ -68,6 +68,8 @@ const char* ExtensionToString(Extension extension) {
|
||||
return "SPV_KHR_shader_atomic_counter_ops";
|
||||
case Extension::kSPV_KHR_shader_ballot:
|
||||
return "SPV_KHR_shader_ballot";
|
||||
case Extension::kSPV_KHR_shader_clock:
|
||||
return "SPV_KHR_shader_clock";
|
||||
case Extension::kSPV_KHR_shader_draw_parameters:
|
||||
return "SPV_KHR_shader_draw_parameters";
|
||||
case Extension::kSPV_KHR_storage_buffer_storage_class:
|
||||
@@ -115,8 +117,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_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_media_block_io", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_device_group", "SPV_KHR_float_controls", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_post_depth_coverage", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_vote", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_NVX_multiview_per_view_attributes", "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_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_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_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_device_side_avc_motion_estimation, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_NVX_multiview_per_view_attributes, 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_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_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_media_block_io", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_device_group", "SPV_KHR_float_controls", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_post_depth_coverage", "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_vote", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_NVX_multiview_per_view_attributes", "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_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_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_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_device_side_avc_motion_estimation, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_post_depth_coverage, 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_vote, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_NVX_multiview_per_view_attributes, 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_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique };
|
||||
const auto b = std::begin(known_ext_strs);
|
||||
const auto e = std::end(known_ext_strs);
|
||||
const auto found = std::equal_range(
|
||||
@@ -318,6 +320,8 @@ const char* CapabilityToString(SpvCapability capability) {
|
||||
return "StencilExportEXT";
|
||||
case SpvCapabilityImageReadWriteLodAMD:
|
||||
return "ImageReadWriteLodAMD";
|
||||
case SpvCapabilityShaderClockKHR:
|
||||
return "ShaderClockKHR";
|
||||
case SpvCapabilitySampleMaskOverrideCoverageNV:
|
||||
return "SampleMaskOverrideCoverageNV";
|
||||
case SpvCapabilityGeometryShaderPassthroughNV:
|
||||
@@ -412,4 +416,4 @@ const char* CapabilityToString(SpvCapability capability) {
|
||||
};
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ kSPV_KHR_no_integer_wrap_decoration,
|
||||
kSPV_KHR_post_depth_coverage,
|
||||
kSPV_KHR_shader_atomic_counter_ops,
|
||||
kSPV_KHR_shader_ballot,
|
||||
kSPV_KHR_shader_clock,
|
||||
kSPV_KHR_shader_draw_parameters,
|
||||
kSPV_KHR_storage_buffer_storage_class,
|
||||
kSPV_KHR_subgroup_vote,
|
||||
@@ -51,4 +52,4 @@ kSPV_NV_shader_subgroup_partitioned,
|
||||
kSPV_NV_shading_rate,
|
||||
kSPV_NV_stereo_view_rendering,
|
||||
kSPV_NV_viewport_array2,
|
||||
kSPV_VALIDATOR_ignore_type_decl_unique
|
||||
kSPV_VALIDATOR_ignore_type_decl_unique
|
||||
@@ -20,4 +20,4 @@
|
||||
{19, "Clay", "Clay Shader Compiler", "Clay Clay Shader Compiler"},
|
||||
{20, "W3C WebGPU Group", "WHLSL Shader Translator", "W3C WebGPU Group WHLSL Shader Translator"},
|
||||
{21, "Google", "Clspv", "Google Clspv"},
|
||||
{22, "Google", "MLIR SPIR-V Serializer", "Google MLIR SPIR-V Serializer"},
|
||||
{22, "Google", "MLIR SPIR-V Serializer", "Google MLIR SPIR-V Serializer"},
|
||||
@@ -83,4 +83,4 @@ static const spv_ext_inst_desc_t glsl_entries[] = {
|
||||
{"NMin", 79, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"NMax", 80, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"NClamp", 81, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
};
|
||||
@@ -163,4 +163,4 @@ static const spv_ext_inst_desc_t opencl_entries[] = {
|
||||
{"u_abs_diff", 202, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_mul_hi", 203, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_mad_hi", 204, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
};
|
||||
@@ -114,6 +114,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_no_integer_wrap_dec
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_post_depth_coverage[] = {spvtools::Extension::kSPV_KHR_post_depth_coverage};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_atomic_counter_ops[] = {spvtools::Extension::kSPV_KHR_shader_atomic_counter_ops};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_draw_parameters[] = {spvtools::Extension::kSPV_KHR_shader_draw_parameters};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_draw_parametersSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_KHR_shader_draw_parameters, spvtools::Extension::kSPV_NV_mesh_shader};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_storage_buffer_storage_classSPV_KHR_variable_pointers[] = {spvtools::Extension::kSPV_KHR_storage_buffer_storage_class, spvtools::Extension::kSPV_KHR_variable_pointers};
|
||||
@@ -781,6 +782,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"FragmentMaskAMD", 5010, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"StencilExportEXT", 5013, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ImageReadWriteLodAMD", 5015, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_image_load_store_lod, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ShaderClockKHR", 5055, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_clock, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"SampleMaskOverrideCoverageNV", 5249, 1, pygen_variable_caps_SampleRateShading, 1, pygen_variable_exts_SPV_NV_sample_mask_override_coverage, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"GeometryShaderPassthroughNV", 5251, 1, pygen_variable_caps_Geometry, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ShaderViewportIndexLayerEXT", 5254, 1, pygen_variable_caps_MultiViewport, 2, pygen_variable_exts_SPV_EXT_shader_viewport_index_layerSPV_NV_viewport_array2, {}, 0xffffffffu, 0xffffffffu},
|
||||
@@ -921,4 +923,4 @@ static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = {
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_IMAGE, ARRAY_SIZE(pygen_variable_ImageOperandsEntries), pygen_variable_ImageOperandsEntries},
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries},
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER, ARRAY_SIZE(pygen_variable_AccessQualifierEntries), pygen_variable_AccessQualifierEntries}
|
||||
};
|
||||
};
|
||||
@@ -4,4 +4,4 @@ static const spv_ext_inst_desc_t spv_amd_gcn_shader_entries[] = {
|
||||
{"CubeFaceIndexAMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"CubeFaceCoordAMD", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"TimeAMD", 3, 0, nullptr, {SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
};
|
||||
@@ -5,4 +5,4 @@ static const spv_ext_inst_desc_t spv_amd_shader_ballot_entries[] = {
|
||||
{"SwizzleInvocationsMaskedAMD", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"WriteInvocationAMD", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"MbcntAMD", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
};
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_shader_explicit_vertex_parameter_entries[] = {
|
||||
{"InterpolateAtVertexAMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
};
|
||||
@@ -10,4 +10,4 @@ static const spv_ext_inst_desc_t spv_amd_shader_trinary_minmax_entries[] = {
|
||||
{"FMid3AMD", 7, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UMid3AMD", 8, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SMid3AMD", 9, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
||||
};
|
||||
@@ -490,6 +490,28 @@ bool AggressiveDCEPass::AggressiveDCE(Function* func) {
|
||||
ProcessLoad(varId);
|
||||
}
|
||||
}
|
||||
|
||||
// Add OpDecorateId instructions that apply to this instruction to the work
|
||||
// list. We use the decoration manager to look through the group
|
||||
// decorations to get to the OpDecorate* instructions themselves.
|
||||
auto decorations =
|
||||
get_decoration_mgr()->GetDecorationsFor(liveInst->result_id(), false);
|
||||
for (Instruction* dec : decorations) {
|
||||
// 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) {
|
||||
continue;
|
||||
}
|
||||
if (dec->GetSingleWordInOperand(1) ==
|
||||
SpvDecorationHlslCounterBufferGOOGLE) {
|
||||
// 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;
|
||||
}
|
||||
AddToWorklist(dec);
|
||||
}
|
||||
|
||||
worklist_.pop();
|
||||
}
|
||||
|
||||
@@ -618,14 +640,6 @@ Pass::Status AggressiveDCEPass::ProcessImpl() {
|
||||
// return unmodified.
|
||||
if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
|
||||
|
||||
// If the decoration manager is kept live then the context will try to keep it
|
||||
// up to date. ADCE deals with group decorations by changing the operands in
|
||||
// |OpGroupDecorate| instruction directly without informing the decoration
|
||||
// manager. This can put it in an invalid state which will cause an error
|
||||
// when the context tries to update it. To avoid this problem invalidate
|
||||
// the decoration manager upfront.
|
||||
context()->InvalidateAnalyses(IRContext::Analysis::kAnalysisDecorations);
|
||||
|
||||
// Eliminate Dead functions.
|
||||
bool modified = EliminateDeadFunctions();
|
||||
|
||||
@@ -635,6 +649,17 @@ Pass::Status AggressiveDCEPass::ProcessImpl() {
|
||||
ProcessFunction pfn = [this](Function* fp) { return AggressiveDCE(fp); };
|
||||
modified |= context()->ProcessEntryPointCallTree(pfn);
|
||||
|
||||
// If the decoration manager is kept live then the context will try to keep it
|
||||
// up to date. ADCE deals with group decorations by changing the operands in
|
||||
// |OpGroupDecorate| instruction directly without informing the decoration
|
||||
// manager. This can put it in an invalid state which will cause an error
|
||||
// when the context tries to update it. To avoid this problem invalidate
|
||||
// the decoration manager upfront.
|
||||
//
|
||||
// We kill it at now because it is used when processing the entry point
|
||||
// functions.
|
||||
context()->InvalidateAnalyses(IRContext::Analysis::kAnalysisDecorations);
|
||||
|
||||
// Process module-level instructions. Now that all live instructions have
|
||||
// been marked, it is safe to remove dead global values.
|
||||
modified |= ProcessGlobalValues();
|
||||
|
||||
@@ -398,20 +398,9 @@ void InstBindlessCheckPass::GenInitCheckCode(
|
||||
void InstBindlessCheckPass::InitializeInstBindlessCheck() {
|
||||
// Initialize base class
|
||||
InitializeInstrument();
|
||||
// Look for related extensions
|
||||
ext_descriptor_indexing_defined_ = false;
|
||||
for (auto& ei : get_module()->extensions()) {
|
||||
const char* ext_name =
|
||||
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
|
||||
if (strcmp(ext_name, "SPV_EXT_descriptor_indexing") == 0) {
|
||||
ext_descriptor_indexing_defined_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If descriptor indexing extension and runtime array length support enabled,
|
||||
// create variable mappings. Length support is always enabled if descriptor
|
||||
// init check is enabled.
|
||||
if (ext_descriptor_indexing_defined_ && input_length_enabled_)
|
||||
// If runtime array length support enabled, create variable mappings. Length
|
||||
// support is always enabled if descriptor init check is enabled.
|
||||
if (input_length_enabled_)
|
||||
for (auto& anno : get_module()->annotations())
|
||||
if (anno.opcode() == SpvOpDecorate) {
|
||||
if (anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet)
|
||||
@@ -433,7 +422,7 @@ Pass::Status InstBindlessCheckPass::ProcessImpl() {
|
||||
new_blocks);
|
||||
};
|
||||
bool modified = InstProcessEntryPointCallTree(pfn);
|
||||
if (ext_descriptor_indexing_defined_ && input_init_enabled_) {
|
||||
if (input_init_enabled_) {
|
||||
// Perform descriptor initialization check on each entry point function in
|
||||
// module
|
||||
pfn = [this](BasicBlock::iterator ref_inst_itr,
|
||||
|
||||
@@ -162,9 +162,6 @@ class InstBindlessCheckPass : public InstrumentPass {
|
||||
// GenInitCheckCode to every instruction in module.
|
||||
Pass::Status ProcessImpl();
|
||||
|
||||
// True if VK_EXT_descriptor_indexing is defined
|
||||
bool ext_descriptor_indexing_defined_;
|
||||
|
||||
// Enable instrumentation of runtime array length checking
|
||||
bool input_length_enabled_;
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ bool MergeReturnPass::ProcessStructured(
|
||||
return false;
|
||||
}
|
||||
|
||||
RecordImmediateDominators(function);
|
||||
AddDummyLoopAroundFunction();
|
||||
|
||||
std::list<BasicBlock*> order;
|
||||
@@ -236,10 +237,6 @@ void MergeReturnPass::UpdatePhiNodes(BasicBlock* new_source,
|
||||
inst->AddOperand({SPV_OPERAND_TYPE_ID, {new_source->id()}});
|
||||
context()->UpdateDefUse(inst);
|
||||
});
|
||||
|
||||
// Store the immediate dominator for this block in case new phi nodes will be
|
||||
// needed later.
|
||||
RecordImmediateDominator(target);
|
||||
}
|
||||
|
||||
void MergeReturnPass::CreatePhiNodesForInst(BasicBlock* merge_block,
|
||||
@@ -683,7 +680,7 @@ void MergeReturnPass::AddNewPhiNodes(BasicBlock* bb) {
|
||||
return;
|
||||
}
|
||||
|
||||
BasicBlock* current_bb = new_merge_nodes_[bb];
|
||||
BasicBlock* current_bb = context()->get_instr_block(original_dominator_[bb]);
|
||||
while (current_bb != nullptr && current_bb != dominator) {
|
||||
for (Instruction& inst : *current_bb) {
|
||||
CreatePhiNodesForInst(bb, inst);
|
||||
@@ -692,11 +689,16 @@ void MergeReturnPass::AddNewPhiNodes(BasicBlock* bb) {
|
||||
}
|
||||
}
|
||||
|
||||
void MergeReturnPass::RecordImmediateDominator(BasicBlock* block) {
|
||||
DominatorAnalysis* dom_tree =
|
||||
context()->GetDominatorAnalysis(block->GetParent());
|
||||
auto idom = dom_tree->ImmediateDominator(block);
|
||||
new_merge_nodes_[block] = idom;
|
||||
void MergeReturnPass::RecordImmediateDominators(Function* function) {
|
||||
DominatorAnalysis* dom_tree = context()->GetDominatorAnalysis(function);
|
||||
for (BasicBlock& bb : *function) {
|
||||
BasicBlock* dominator_bb = dom_tree->ImmediateDominator(&bb);
|
||||
if (dominator_bb && dominator_bb != cfg()->pseudo_entry_block()) {
|
||||
original_dominator_[&bb] = dominator_bb->terminator();
|
||||
} else {
|
||||
original_dominator_[&bb] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MergeReturnPass::InsertAfterElement(BasicBlock* element,
|
||||
|
||||
@@ -246,24 +246,23 @@ class MergeReturnPass : public MemPass {
|
||||
// instruction.
|
||||
void CreatePhiNodesForInst(BasicBlock* merge_block, Instruction& inst);
|
||||
|
||||
// Traverse the nodes in |new_merge_nodes_|, and adds the OpPhi instructions
|
||||
// that are needed to make the code correct. It is assumed that at this point
|
||||
// there are no unreachable blocks in the control flow graph.
|
||||
// Add new phi nodes for any id that no longer dominate all of it uses. A phi
|
||||
// node is added to a block |bb| for an id if the id is defined between the
|
||||
// original immediate dominator of |bb| and its new immidiate dominator. It
|
||||
// is assumed that at this point there are no unreachable blocks in the
|
||||
// control flow graph.
|
||||
void AddNewPhiNodes();
|
||||
|
||||
// Creates any new phi nodes that are needed in |bb|. |AddNewPhiNodes| must
|
||||
// have already been called on the original dominators of |bb|.
|
||||
void AddNewPhiNodes(BasicBlock* bb);
|
||||
|
||||
// Saves |block| to a list of basic block that will require OpPhi nodes to be
|
||||
// added by calling |AddNewPhiNodes|. It is assumed that |block| used to have
|
||||
// a single predecessor, |single_original_pred|, but now has more.
|
||||
void RecordImmediateDominator(BasicBlock* block);
|
||||
// Records the terminator of immediate dominator for every basic block in
|
||||
// |function|.
|
||||
void RecordImmediateDominators(Function* function);
|
||||
|
||||
// Modifies existing OpPhi instruction in |target| block to account for the
|
||||
// new edge from |new_source|. The value for that edge will be an Undef. If
|
||||
// |target| only had a single predecessor, then it is marked as needing new
|
||||
// phi nodes. See |RecordImmediateDominator|.
|
||||
// new edge from |new_source|. The value for that edge will be an Undef.
|
||||
//
|
||||
// The CFG must not include the edge from |new_source| to |target| yet.
|
||||
void UpdatePhiNodes(BasicBlock* new_source, BasicBlock* target);
|
||||
@@ -317,9 +316,10 @@ class MergeReturnPass : public MemPass {
|
||||
// after processing the current function.
|
||||
BasicBlock* final_return_block_;
|
||||
|
||||
// This is a map from a node to its original immediate dominator. This is
|
||||
// used to determine which values will require a new phi node.
|
||||
std::unordered_map<BasicBlock*, BasicBlock*> new_merge_nodes_;
|
||||
// This is a map from a node to its original immediate dominator identified by
|
||||
// the terminator if that block. We use the terminator because the block we
|
||||
// want may change if the block is split.
|
||||
std::unordered_map<BasicBlock*, Instruction*> original_dominator_;
|
||||
|
||||
// A map from a basic block, bb, to the set of basic blocks which represent
|
||||
// the new edges that reach |bb|.
|
||||
|
||||
@@ -102,6 +102,7 @@ void SSARewriter::ReplacePhiUsersWith(const PhiCandidate& phi_to_remove,
|
||||
uint32_t repl_id) {
|
||||
for (uint32_t user_id : phi_to_remove.users()) {
|
||||
PhiCandidate* user_phi = GetPhiCandidate(user_id);
|
||||
BasicBlock* bb = pass_->context()->get_instr_block(user_id);
|
||||
if (user_phi) {
|
||||
// If the user is a Phi candidate, replace all arguments that refer to
|
||||
// |phi_to_remove.result_id()| with |repl_id|.
|
||||
@@ -110,6 +111,10 @@ void SSARewriter::ReplacePhiUsersWith(const PhiCandidate& phi_to_remove,
|
||||
arg = repl_id;
|
||||
}
|
||||
}
|
||||
} else if (bb->id() == user_id) {
|
||||
// The phi candidate is the definition of the variable at basic block
|
||||
// |bb|. We must change this to the replacement.
|
||||
WriteVariable(phi_to_remove.var_id(), bb, repl_id);
|
||||
} else {
|
||||
// For regular loads, traverse the |load_replacement_| table looking for
|
||||
// instances of |phi_to_remove|.
|
||||
@@ -259,6 +264,8 @@ uint32_t SSARewriter::GetReachingDef(uint32_t var_id, BasicBlock* bb) {
|
||||
// require a Phi instruction. This will act as |var_id|'s current
|
||||
// definition to break potential cycles.
|
||||
PhiCandidate& phi_candidate = CreatePhiCandidate(var_id, bb);
|
||||
|
||||
// Set the value for |bb| to avoid an infinite recursion.
|
||||
WriteVariable(var_id, bb, phi_candidate.result_id());
|
||||
val_id = AddPhiOperands(&phi_candidate);
|
||||
}
|
||||
|
||||
@@ -188,6 +188,9 @@ class SSARewriter {
|
||||
// value |val_id|.
|
||||
void WriteVariable(uint32_t var_id, BasicBlock* bb, uint32_t val_id) {
|
||||
defs_at_block_[bb][var_id] = val_id;
|
||||
if (auto* pc = GetPhiCandidate(val_id)) {
|
||||
pc->AddUser(bb->id());
|
||||
}
|
||||
}
|
||||
|
||||
// Processes the store operation |inst| in basic block |bb|. This extracts
|
||||
|
||||
15
3rdparty/spirv-tools/source/val/function.cpp
vendored
15
3rdparty/spirv-tools/source/val/function.cpp
vendored
@@ -317,13 +317,10 @@ int Function::GetBlockDepth(BasicBlock* bb) {
|
||||
if (!bb_dom || bb == bb_dom) {
|
||||
// This block has no dominator, so it's at depth 0.
|
||||
block_depth_[bb] = 0;
|
||||
} else if (bb->is_type(kBlockTypeMerge)) {
|
||||
// If this is a merge block, its depth is equal to the block before
|
||||
// branching.
|
||||
BasicBlock* header = merge_block_header_[bb];
|
||||
assert(header);
|
||||
block_depth_[bb] = GetBlockDepth(header);
|
||||
} else if (bb->is_type(kBlockTypeContinue)) {
|
||||
// This rule must precede the rule for merge blocks in order to set up
|
||||
// depths correctly. If a block is both a merge and continue then the merge
|
||||
// is nested within the continue's loop (or the graph is incorrect).
|
||||
// The depth of the continue block entry point is 1 + loop header depth.
|
||||
Construct* continue_construct =
|
||||
entry_block_to_construct_[std::make_pair(bb, ConstructType::kContinue)];
|
||||
@@ -341,6 +338,12 @@ int Function::GetBlockDepth(BasicBlock* bb) {
|
||||
} else {
|
||||
block_depth_[bb] = 1 + GetBlockDepth(loop_header);
|
||||
}
|
||||
} else if (bb->is_type(kBlockTypeMerge)) {
|
||||
// If this is a merge block, its depth is equal to the block before
|
||||
// branching.
|
||||
BasicBlock* header = merge_block_header_[bb];
|
||||
assert(header);
|
||||
block_depth_[bb] = GetBlockDepth(header);
|
||||
} else if (bb_dom->is_type(kBlockTypeHeader) ||
|
||||
bb_dom->is_type(kBlockTypeLoop)) {
|
||||
// The dominator of the given block is a header block. So, the nesting
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/val/validate.h"
|
||||
|
||||
#include "source/opcode.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/val/instruction.h"
|
||||
#include "source/val/validate.h"
|
||||
#include "source/val/validation_state.h"
|
||||
|
||||
namespace spvtools {
|
||||
@@ -287,11 +286,11 @@ spv_result_t ValidateDecorationGroup(ValidationState_t& _,
|
||||
auto use = pair.first;
|
||||
if (use->opcode() != SpvOpDecorate && use->opcode() != SpvOpGroupDecorate &&
|
||||
use->opcode() != SpvOpGroupMemberDecorate &&
|
||||
use->opcode() != SpvOpName) {
|
||||
use->opcode() != SpvOpName && use->opcode() != SpvOpDecorateId) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "Result id of OpDecorationGroup can only "
|
||||
<< "be targeted by OpName, OpGroupDecorate, "
|
||||
<< "OpDecorate, and OpGroupMemberDecorate";
|
||||
<< "OpDecorate, OpDecorateId, and OpGroupMemberDecorate";
|
||||
}
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
|
||||
@@ -25,6 +25,28 @@
|
||||
#include "source/val/validate_scopes.h"
|
||||
#include "source/val/validation_state.h"
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsStorageClassAllowedByUniversalRules(uint32_t storage_class) {
|
||||
switch (storage_class) {
|
||||
case SpvStorageClassUniform:
|
||||
case SpvStorageClassStorageBuffer:
|
||||
case SpvStorageClassWorkgroup:
|
||||
case SpvStorageClassCrossWorkgroup:
|
||||
case SpvStorageClassGeneric:
|
||||
case SpvStorageClassAtomicCounter:
|
||||
case SpvStorageClassImage:
|
||||
case SpvStorageClassFunction:
|
||||
case SpvStorageClassPhysicalStorageBufferEXT:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace spvtools {
|
||||
namespace val {
|
||||
|
||||
@@ -119,32 +141,42 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
|
||||
<< ": expected Pointer to be of type OpTypePointer";
|
||||
}
|
||||
|
||||
switch (storage_class) {
|
||||
case SpvStorageClassUniform:
|
||||
case SpvStorageClassWorkgroup:
|
||||
case SpvStorageClassCrossWorkgroup:
|
||||
case SpvStorageClassGeneric:
|
||||
case SpvStorageClassAtomicCounter:
|
||||
case SpvStorageClassImage:
|
||||
case SpvStorageClassStorageBuffer:
|
||||
case SpvStorageClassPhysicalStorageBufferEXT:
|
||||
break;
|
||||
default:
|
||||
if (spvIsOpenCLEnv(_.context()->target_env)) {
|
||||
if (storage_class != SpvStorageClassFunction) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": expected Pointer Storage Class to be Uniform, "
|
||||
"Workgroup, CrossWorkgroup, Generic, AtomicCounter, "
|
||||
"Image, StorageBuffer or Function";
|
||||
}
|
||||
} else {
|
||||
// Validate storage class against universal rules
|
||||
if (!IsStorageClassAllowedByUniversalRules(storage_class)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": storage class forbidden by universal validation rules.";
|
||||
}
|
||||
|
||||
// Then Shader rules
|
||||
if (_.HasCapability(SpvCapabilityShader)) {
|
||||
if (storage_class == SpvStorageClassFunction) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": Function storage class forbidden when the Shader "
|
||||
"capability is declared.";
|
||||
}
|
||||
}
|
||||
|
||||
// And finally OpenCL environment rules
|
||||
if (spvIsOpenCLEnv(_.context()->target_env)) {
|
||||
if ((storage_class != SpvStorageClassFunction) &&
|
||||
(storage_class != SpvStorageClassWorkgroup) &&
|
||||
(storage_class != SpvStorageClassCrossWorkgroup) &&
|
||||
(storage_class != SpvStorageClassGeneric)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": storage class must be Function, Workgroup, "
|
||||
"CrossWorkGroup or Generic in the OpenCL environment.";
|
||||
}
|
||||
|
||||
if (_.context()->target_env == SPV_ENV_OPENCL_1_2) {
|
||||
if (storage_class == SpvStorageClassGeneric) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< spvOpcodeString(opcode)
|
||||
<< ": expected Pointer Storage Class to be Uniform, "
|
||||
"Workgroup, CrossWorkgroup, Generic, AtomicCounter, "
|
||||
"Image or StorageBuffer";
|
||||
<< "Storage class cannot be Generic in OpenCL 1.2 "
|
||||
"environment";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == SpvOpAtomicFlagTestAndSet ||
|
||||
|
||||
67
3rdparty/spirv-tools/source/val/validate_cfg.cpp
vendored
67
3rdparty/spirv-tools/source/val/validate_cfg.cpp
vendored
@@ -493,41 +493,54 @@ spv_result_t StructuredSwitchChecks(ValidationState_t& _, Function* function,
|
||||
std::map<uint32_t, uint32_t> num_fall_through_targeted;
|
||||
uint32_t default_case_fall_through = 0u;
|
||||
uint32_t default_target = switch_inst->GetOperandAs<uint32_t>(1u);
|
||||
std::unordered_set<uint32_t> seen;
|
||||
bool default_appears_multiple_times = false;
|
||||
for (uint32_t i = 3; i < switch_inst->operands().size(); i += 2) {
|
||||
if (default_target == switch_inst->GetOperandAs<uint32_t>(i)) {
|
||||
default_appears_multiple_times = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::unordered_map<uint32_t, uint32_t> seen_to_fall_through;
|
||||
for (uint32_t i = 1; i < switch_inst->operands().size(); i += 2) {
|
||||
uint32_t target = switch_inst->GetOperandAs<uint32_t>(i);
|
||||
if (target == merge->id()) continue;
|
||||
|
||||
if (!seen.insert(target).second) continue;
|
||||
|
||||
const auto target_block = function->GetBlock(target).first;
|
||||
// OpSwitch must dominate all its case constructs.
|
||||
if (header->reachable() && target_block->reachable() &&
|
||||
!header->dominates(*target_block)) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG, header->label())
|
||||
<< "Selection header " << _.getIdName(header->id())
|
||||
<< " does not dominate its case construct " << _.getIdName(target);
|
||||
}
|
||||
|
||||
uint32_t case_fall_through = 0u;
|
||||
if (auto error = FindCaseFallThrough(_, target_block, &case_fall_through,
|
||||
merge, case_targets, function)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// Track how many time the fall through case has been targeted.
|
||||
if (case_fall_through != 0u) {
|
||||
auto where = num_fall_through_targeted.lower_bound(case_fall_through);
|
||||
if (where == num_fall_through_targeted.end() ||
|
||||
where->first != case_fall_through) {
|
||||
num_fall_through_targeted.insert(where,
|
||||
std::make_pair(case_fall_through, 1));
|
||||
} else {
|
||||
where->second++;
|
||||
auto seen_iter = seen_to_fall_through.find(target);
|
||||
if (seen_iter == seen_to_fall_through.end()) {
|
||||
const auto target_block = function->GetBlock(target).first;
|
||||
// OpSwitch must dominate all its case constructs.
|
||||
if (header->reachable() && target_block->reachable() &&
|
||||
!header->dominates(*target_block)) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG, header->label())
|
||||
<< "Selection header " << _.getIdName(header->id())
|
||||
<< " does not dominate its case construct "
|
||||
<< _.getIdName(target);
|
||||
}
|
||||
|
||||
if (auto error = FindCaseFallThrough(_, target_block, &case_fall_through,
|
||||
merge, case_targets, function)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// Track how many time the fall through case has been targeted.
|
||||
if (case_fall_through != 0u) {
|
||||
auto where = num_fall_through_targeted.lower_bound(case_fall_through);
|
||||
if (where == num_fall_through_targeted.end() ||
|
||||
where->first != case_fall_through) {
|
||||
num_fall_through_targeted.insert(
|
||||
where, std::make_pair(case_fall_through, 1));
|
||||
} else {
|
||||
where->second++;
|
||||
}
|
||||
}
|
||||
seen_to_fall_through.insert(std::make_pair(target, case_fall_through));
|
||||
} else {
|
||||
case_fall_through = seen_iter->second;
|
||||
}
|
||||
|
||||
if (case_fall_through == default_target) {
|
||||
if (case_fall_through == default_target &&
|
||||
!default_appears_multiple_times) {
|
||||
case_fall_through = default_case_fall_through;
|
||||
}
|
||||
if (case_fall_through != 0u) {
|
||||
|
||||
@@ -53,37 +53,45 @@ spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst) {
|
||||
<< "Expected P type and Result Type to be the same: "
|
||||
<< spvOpcodeString(opcode);
|
||||
}
|
||||
|
||||
const spvtools::Extension compute_shader_derivatives_extension =
|
||||
kSPV_NV_compute_shader_derivatives;
|
||||
ExtensionSet exts(1, &compute_shader_derivatives_extension);
|
||||
|
||||
if (_.HasAnyOfExtensions(exts)) {
|
||||
_.function(inst->function()->id())
|
||||
->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
|
||||
std::string* message) {
|
||||
if (model != SpvExecutionModelFragment &&
|
||||
model != SpvExecutionModelGLCompute) {
|
||||
if (message) {
|
||||
*message =
|
||||
std::string(
|
||||
"Derivative instructions require Fragment execution "
|
||||
"model: ") +
|
||||
spvOpcodeString(opcode);
|
||||
}
|
||||
return false;
|
||||
_.function(inst->function()->id())
|
||||
->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
|
||||
std::string* message) {
|
||||
if (model != SpvExecutionModelFragment &&
|
||||
model != SpvExecutionModelGLCompute) {
|
||||
if (message) {
|
||||
*message =
|
||||
std::string(
|
||||
"Derivative instructions require Fragment or GLCompute "
|
||||
"execution model: ") +
|
||||
spvOpcodeString(opcode);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
_.function(inst->function()->id())
|
||||
->RegisterExecutionModelLimitation(
|
||||
SpvExecutionModelFragment,
|
||||
std::string(
|
||||
"Derivative instructions require Fragment execution "
|
||||
"model: ") +
|
||||
spvOpcodeString(opcode));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
_.function(inst->function()->id())
|
||||
->RegisterLimitation([opcode](const ValidationState_t& state,
|
||||
const Function* entry_point,
|
||||
std::string* message) {
|
||||
const auto* models = state.GetExecutionModels(entry_point->id());
|
||||
const auto* modes = state.GetExecutionModes(entry_point->id());
|
||||
if (models->find(SpvExecutionModelGLCompute) != models->end() &&
|
||||
modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
|
||||
modes->end() &&
|
||||
modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
|
||||
modes->end()) {
|
||||
if (message) {
|
||||
*message = std::string(
|
||||
"Derivative instructions require "
|
||||
"DerivativeGroupQuadsNV "
|
||||
"or DerivativeGroupLinearNV execution mode for "
|
||||
"GLCompute execution model: ") +
|
||||
spvOpcodeString(opcode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1710,8 +1710,39 @@ spv_result_t ValidateImageQueryLod(ValidationState_t& _,
|
||||
const Instruction* inst) {
|
||||
_.function(inst->function()->id())
|
||||
->RegisterExecutionModelLimitation(
|
||||
SpvExecutionModelFragment,
|
||||
"OpImageQueryLod requires Fragment execution model");
|
||||
[&](SpvExecutionModel model, std::string* message) {
|
||||
if (model != SpvExecutionModelFragment &&
|
||||
model != SpvExecutionModelGLCompute) {
|
||||
if (message) {
|
||||
*message = std::string(
|
||||
"OpImageQueryLod requires Fragment or GLCompute execution "
|
||||
"model");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
_.function(inst->function()->id())
|
||||
->RegisterLimitation([](const ValidationState_t& state,
|
||||
const Function* entry_point,
|
||||
std::string* message) {
|
||||
const auto* models = state.GetExecutionModels(entry_point->id());
|
||||
const auto* modes = state.GetExecutionModes(entry_point->id());
|
||||
if (models->find(SpvExecutionModelGLCompute) != models->end() &&
|
||||
modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
|
||||
modes->end() &&
|
||||
modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
|
||||
modes->end()) {
|
||||
if (message) {
|
||||
*message = std::string(
|
||||
"OpImageQueryLod requires DerivativeGroupQuadsNV "
|
||||
"or DerivativeGroupLinearNV execution mode for GLCompute "
|
||||
"execution model");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
const uint32_t result_type = inst->type_id();
|
||||
if (!_.IsFloatVectorType(result_type)) {
|
||||
@@ -1835,9 +1866,44 @@ spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) {
|
||||
const SpvOp opcode = inst->opcode();
|
||||
if (IsImplicitLod(opcode)) {
|
||||
_.function(inst->function()->id())
|
||||
->RegisterExecutionModelLimitation(
|
||||
SpvExecutionModelFragment,
|
||||
"ImplicitLod instructions require Fragment execution model");
|
||||
->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
|
||||
std::string* message) {
|
||||
if (model != SpvExecutionModelFragment &&
|
||||
model != SpvExecutionModelGLCompute) {
|
||||
if (message) {
|
||||
*message =
|
||||
std::string(
|
||||
"ImplicitLod instructions require Fragment or GLCompute "
|
||||
"execution model: ") +
|
||||
spvOpcodeString(opcode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
_.function(inst->function()->id())
|
||||
->RegisterLimitation([opcode](const ValidationState_t& state,
|
||||
const Function* entry_point,
|
||||
std::string* message) {
|
||||
const auto* models = state.GetExecutionModels(entry_point->id());
|
||||
const auto* modes = state.GetExecutionModes(entry_point->id());
|
||||
if (models->find(SpvExecutionModelGLCompute) != models->end() &&
|
||||
modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
|
||||
modes->end() &&
|
||||
modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
|
||||
modes->end()) {
|
||||
if (message) {
|
||||
*message =
|
||||
std::string(
|
||||
"ImplicitLod instructions require DerivativeGroupQuadsNV "
|
||||
"or DerivativeGroupLinearNV execution mode for GLCompute "
|
||||
"execution model: ") +
|
||||
spvOpcodeString(opcode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
|
||||
@@ -6560,6 +6560,62 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true);
|
||||
}
|
||||
|
||||
TEST_F(AggressiveDCETest, LiveDecorateId) {
|
||||
const std::string spirv = R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %1 "main" %2
|
||||
OpExecutionMode %1 LocalSize 8 1 1
|
||||
OpDecorate %2 DescriptorSet 0
|
||||
OpDecorate %2 Binding 0
|
||||
OpDecorateId %3 UniformId %uint_2
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
|
||||
%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
|
||||
%8 = OpTypeFunction %void
|
||||
%1 = OpFunction %void None %8
|
||||
%9 = OpLabel
|
||||
%3 = OpLoad %uint %2
|
||||
OpStore %2 %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
|
||||
OptimizerOptions()->preserve_spec_constants_ = true;
|
||||
SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
|
||||
}
|
||||
|
||||
TEST_F(AggressiveDCETest, LiveDecorateIdOnGroup) {
|
||||
const std::string spirv = R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %1 "main" %2
|
||||
OpExecutionMode %1 LocalSize 8 1 1
|
||||
OpDecorate %2 DescriptorSet 0
|
||||
OpDecorate %2 Binding 0
|
||||
OpDecorateId %3 UniformId %uint_2
|
||||
%3 = OpDecorationGroup
|
||||
OpGroupDecorate %3 %5
|
||||
%void = OpTypeVoid
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_2 = OpConstant %uint 2
|
||||
%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
|
||||
%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer
|
||||
%9 = OpTypeFunction %void
|
||||
%1 = OpFunction %void None %9
|
||||
%10 = OpLabel
|
||||
%5 = OpLoad %uint %2
|
||||
OpStore %2 %5
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_UNIVERSAL_1_4);
|
||||
OptimizerOptions()->preserve_spec_constants_ = true;
|
||||
SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Check that logical addressing required
|
||||
|
||||
@@ -255,7 +255,7 @@ OpFunctionEnd
|
||||
func_pt2_before,
|
||||
entry_after + names_annots + new_annots + consts_types_vars +
|
||||
new_consts_types_vars + func_pt1 + func_pt2_after + output_func,
|
||||
true, true);
|
||||
true, true, 7u, 23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, NoInstrumentConstIndexInbounds) {
|
||||
@@ -335,7 +335,8 @@ OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(before, before, true, true);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(before, before, true, true, 7u,
|
||||
23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentMultipleInstructions) {
|
||||
@@ -630,7 +631,7 @@ OpFunctionEnd
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true);
|
||||
true, 7u, 23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentOpImage) {
|
||||
@@ -858,7 +859,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true);
|
||||
true, 7u, 23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentSampledImage) {
|
||||
@@ -1081,7 +1082,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true);
|
||||
true, 7u, 23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentImageWrite) {
|
||||
@@ -1306,7 +1307,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true);
|
||||
true, 7u, 23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentVertexSimple) {
|
||||
@@ -1580,7 +1581,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true);
|
||||
true, 7u, 23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, MultipleDebugFunctions) {
|
||||
@@ -1903,7 +1904,8 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func1_before + func2_before,
|
||||
defs_after + func1_after + func2_after + output_func, true, true);
|
||||
defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u,
|
||||
false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, RuntimeArray) {
|
||||
@@ -2276,18 +2278,19 @@ OpFunctionEnd
|
||||
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(whole_file, whole_file, true,
|
||||
true);
|
||||
true, 7u, 23u, false, false, 1u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptor) {
|
||||
// This test verifies that the pass will correctly instrument vanilla
|
||||
// texture sample on a scalar descriptor with an initialization check if the
|
||||
// SPV_EXT_descriptor_checking extension is enabled. This is the same shader
|
||||
// as NoInstrumentNonBindless, but with the extension hacked on in the SPIR-V.
|
||||
// input_init_enable argument is set to true. This can happen when the
|
||||
// descriptor indexing extension is enabled in the API but the SPIR-V
|
||||
// does not have the extension enabled because it does not contain a
|
||||
// runtime array. This is the same shader as NoInstrumentNonBindless.
|
||||
|
||||
const std::string defs_before =
|
||||
R"(OpCapability Shader
|
||||
OpExtension "SPV_EXT_descriptor_indexing"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
|
||||
@@ -2324,7 +2327,6 @@ OpDecorate %_entryPointOutput_vColor Location 0
|
||||
|
||||
const std::string defs_after =
|
||||
R"(OpCapability Shader
|
||||
OpExtension "SPV_EXT_descriptor_indexing"
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
@@ -2395,7 +2397,7 @@ OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
%uint_6 = OpConstant %uint 6
|
||||
%uint_7 = OpConstant %uint 7
|
||||
%uint_8 = OpConstant %uint 8
|
||||
%uint_40 = OpConstant %uint 40
|
||||
%uint_39 = OpConstant %uint 39
|
||||
%113 = OpConstantNull %v4float
|
||||
)";
|
||||
|
||||
@@ -2429,7 +2431,7 @@ OpBranchConditional %52 %55 %56
|
||||
%59 = OpImageSampleImplicitLod %v4float %58 %20
|
||||
OpBranch %54
|
||||
%56 = OpLabel
|
||||
%112 = OpFunctionCall %void %60 %uint_40 %uint_1 %uint_0 %uint_0
|
||||
%112 = OpFunctionCall %void %60 %uint_39 %uint_1 %uint_0 %uint_0
|
||||
OpBranch %54
|
||||
%54 = OpLabel
|
||||
%114 = OpPhi %v4float %59 %55 %113 %56
|
||||
@@ -4456,7 +4458,7 @@ OpFunctionEnd
|
||||
func_pt2_before,
|
||||
entry_after + names_annots + new_annots + consts_types_vars +
|
||||
new_consts_types_vars + func_pt1 + func_pt2_after + output_func,
|
||||
true, true, 7u, 23u, true, true, 2u);
|
||||
true, true, 7u, 23u, false, false, 2u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentMultipleInstructionsV2) {
|
||||
@@ -4751,7 +4753,7 @@ OpFunctionEnd
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true, 7u, 23u, true, true, 2u);
|
||||
true, 7u, 23u, false, false, 2u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentOpImageV2) {
|
||||
@@ -4979,7 +4981,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true, 7u, 23u, true, true, 2u);
|
||||
true, 7u, 23u, false, false, 2u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentSampledImageV2) {
|
||||
@@ -5202,7 +5204,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true, 7u, 23u, true, true, 2u);
|
||||
true, 7u, 23u, false, false, 2u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentImageWriteV2) {
|
||||
@@ -5427,7 +5429,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true, 7u, 23u, true, true, 2u);
|
||||
true, 7u, 23u, false, false, 2u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, InstrumentVertexSimpleV2) {
|
||||
@@ -5701,7 +5703,7 @@ OpFunctionEnd
|
||||
// SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func_before, defs_after + func_after + output_func, true,
|
||||
true, 7u, 23u, true, true, 2u);
|
||||
true, 7u, 23u, false, false, 2u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, MultipleDebugFunctionsV2) {
|
||||
@@ -6025,7 +6027,7 @@ OpFunctionEnd
|
||||
SinglePassRunAndCheck<InstBindlessCheckPass>(
|
||||
defs_before + func1_before + func2_before,
|
||||
defs_after + func1_after + func2_after + output_func, true, true, 7u, 23u,
|
||||
true, true, 2u);
|
||||
false, false, 2u);
|
||||
}
|
||||
|
||||
TEST_F(InstBindlessTest, RuntimeArrayV2) {
|
||||
@@ -6327,12 +6329,13 @@ OpFunctionEnd
|
||||
TEST_F(InstBindlessTest, InstrumentInitCheckOnScalarDescriptorV2) {
|
||||
// This test verifies that the pass will correctly instrument vanilla
|
||||
// texture sample on a scalar descriptor with an initialization check if the
|
||||
// SPV_EXT_descriptor_checking extension is enabled. This is the same shader
|
||||
// as NoInstrumentNonBindless, but with the extension hacked on in the SPIR-V.
|
||||
// input_init_enable argument is set to true. This can happen when the
|
||||
// descriptor indexing extension is enabled in the API but the SPIR-V
|
||||
// does not have the extension enabled because it does not contain a
|
||||
// runtime array. This is the same shader as NoInstrumentNonBindless.
|
||||
|
||||
const std::string defs_before =
|
||||
R"(OpCapability Shader
|
||||
OpExtension "SPV_EXT_descriptor_indexing"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %MainPs "MainPs" %i_vTextureCoords %_entryPointOutput_vColor
|
||||
@@ -6369,7 +6372,6 @@ OpDecorate %_entryPointOutput_vColor Location 0
|
||||
|
||||
const std::string defs_after =
|
||||
R"(OpCapability Shader
|
||||
OpExtension "SPV_EXT_descriptor_indexing"
|
||||
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
@@ -6440,7 +6442,7 @@ OpDecorate %gl_FragCoord BuiltIn FragCoord
|
||||
%uint_7 = OpConstant %uint 7
|
||||
%uint_8 = OpConstant %uint 8
|
||||
%uint_9 = OpConstant %uint 9
|
||||
%uint_40 = OpConstant %uint 40
|
||||
%uint_39 = OpConstant %uint 39
|
||||
%113 = OpConstantNull %v4float
|
||||
)";
|
||||
|
||||
@@ -6474,7 +6476,7 @@ OpBranchConditional %52 %55 %56
|
||||
%59 = OpImageSampleImplicitLod %v4float %58 %20
|
||||
OpBranch %54
|
||||
%56 = OpLabel
|
||||
%112 = OpFunctionCall %void %60 %uint_40 %uint_1 %uint_0 %uint_0
|
||||
%112 = OpFunctionCall %void %60 %uint_39 %uint_1 %uint_0 %uint_0
|
||||
OpBranch %54
|
||||
%54 = OpLabel
|
||||
%114 = OpPhi %v4float %59 %55 %113 %56
|
||||
|
||||
@@ -1930,6 +1930,63 @@ TEST_F(LocalSSAElimTest, VariablePointerTest2) {
|
||||
SinglePassRunAndMatch<LocalMultiStoreElimPass>(text, false);
|
||||
}
|
||||
|
||||
TEST_F(LocalSSAElimTest, ChainedTrivialPhis) {
|
||||
// Check that the copy object get the undef value implicitly assigned in the
|
||||
// entry block.
|
||||
const std::string text = R"(
|
||||
; CHECK: [[undef:%\w+]] = OpUndef %v4float
|
||||
; CHECK: OpCopyObject %v4float [[undef]]
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %2 "main"
|
||||
OpExecutionMode %2 LocalSize 1 18 6
|
||||
OpSource ESSL 310
|
||||
%void = OpTypeVoid
|
||||
%4 = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%2 = OpFunction %void None %4
|
||||
%9 = OpLabel
|
||||
%10 = OpVariable %_ptr_Function_v4float Function
|
||||
OpBranch %11
|
||||
%11 = OpLabel
|
||||
OpLoopMerge %12 %13 None
|
||||
OpBranch %14
|
||||
%14 = OpLabel
|
||||
%15 = OpUndef %bool
|
||||
OpBranchConditional %15 %16 %12
|
||||
%16 = OpLabel
|
||||
%17 = OpUndef %bool
|
||||
OpSelectionMerge %18 None
|
||||
OpBranchConditional %17 %19 %18
|
||||
%19 = OpLabel
|
||||
%20 = OpUndef %bool
|
||||
OpLoopMerge %21 %22 None
|
||||
OpBranchConditional %20 %23 %21
|
||||
%23 = OpLabel
|
||||
%24 = OpLoad %v4float %10
|
||||
%25 = OpCopyObject %v4float %24
|
||||
%26 = OpUndef %bool
|
||||
OpBranch %22
|
||||
%22 = OpLabel
|
||||
OpBranch %19
|
||||
%21 = OpLabel
|
||||
OpBranch %12
|
||||
%18 = OpLabel
|
||||
OpBranch %13
|
||||
%13 = OpLabel
|
||||
OpBranch %11
|
||||
%12 = OpLabel
|
||||
%27 = OpLoad %v4float %10
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
SinglePassRunAndMatch<SSARewritePass>(text, false);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// No optimization in the presence of
|
||||
|
||||
@@ -1779,6 +1779,57 @@ TEST_F(MergeReturnPassTest, MergeToMergeBranch) {
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<MergeReturnPass>(text, true);
|
||||
}
|
||||
TEST_F(MergeReturnPassTest, PhiInSecondMerge) {
|
||||
// Add and use a phi in the second merge block from the return.
|
||||
const std::string text =
|
||||
R"(
|
||||
; CHECK: OpLoopMerge
|
||||
; CHECK: OpLoopMerge [[merge_bb:%\w+]] [[continue_bb:%\w+]]
|
||||
; CHECK: [[continue_bb]] = OpLabel
|
||||
; CHECK-NEXT: [[val:%\w+]] = OpUndef %float
|
||||
; CHECK: [[merge_bb]] = OpLabel
|
||||
; CHECK-NEXT: [[phi:%\w+]] = OpPhi %float {{%\w+}} {{%\w+}} [[val]] [[continue_bb]]
|
||||
; CHECK-NOT: OpLabel
|
||||
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} [[old_merge:%\w+]]
|
||||
; CHECK: [[old_merge]] = OpLabel
|
||||
; CHECK-NEXT: OpConvertFToS %int [[phi]]
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %2 "main"
|
||||
OpExecutionMode %2 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
%void = OpTypeVoid
|
||||
%4 = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%float = OpTypeFloat 32
|
||||
%bool = OpTypeBool
|
||||
%8 = OpUndef %bool
|
||||
%2 = OpFunction %void None %4
|
||||
%9 = OpLabel
|
||||
OpBranch %10
|
||||
%10 = OpLabel
|
||||
OpLoopMerge %11 %12 None
|
||||
OpBranch %13
|
||||
%13 = OpLabel
|
||||
OpLoopMerge %12 %14 None
|
||||
OpBranchConditional %8 %15 %12
|
||||
%15 = OpLabel
|
||||
OpReturn
|
||||
%14 = OpLabel
|
||||
OpBranch %13
|
||||
%12 = OpLabel
|
||||
%16 = OpUndef %float
|
||||
OpBranchConditional %8 %10 %11
|
||||
%11 = OpLabel
|
||||
%17 = OpConvertFToS %int %16
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<MergeReturnPass>(text, true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
# limitations under the License.
|
||||
"""Tests correctness of opt pass tools/opt --compact-ids."""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
@@ -44,8 +44,6 @@ If --leave-output was not specified, all temporary files and directories will
|
||||
be deleted.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import fnmatch
|
||||
import inspect
|
||||
|
||||
@@ -190,6 +190,9 @@ OpMemoryModel Physical32 OpenCL
|
||||
%f32_ptr_uniformconstant = OpTypePointer UniformConstant %f32
|
||||
%f32_uc_var = OpVariable %f32_ptr_uniformconstant UniformConstant
|
||||
|
||||
%f32_ptr_image = OpTypePointer Image %f32
|
||||
%f32_im_var = OpVariable %f32_ptr_image Image
|
||||
|
||||
%main = OpFunction %void None %func
|
||||
%main_entry = OpLabel
|
||||
)";
|
||||
@@ -288,11 +291,9 @@ OpAtomicStore %f32_var_function %device %relaxed %f32_1
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body), SPV_ENV_VULKAN_1_0);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("AtomicStore: expected Pointer Storage Class to be Uniform, "
|
||||
"Workgroup, CrossWorkgroup, Generic, AtomicCounter, Image or "
|
||||
"StorageBuffer"));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicStore: Function storage class forbidden when "
|
||||
"the Shader capability is declared."));
|
||||
}
|
||||
|
||||
// TODO(atgoo@github.com): the corresponding check fails Vulkan CTS,
|
||||
@@ -500,8 +501,7 @@ TEST_F(ValidateAtomics, AtomicLoadWrongScopeType) {
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("AtomicLoad: expected Memory Scope to be a 32-bit int\n %40 = "
|
||||
"OpAtomicLoad %float %28 %float_1 %uint_0_1\n"));
|
||||
HasSubstr("AtomicLoad: expected Memory Scope to be a 32-bit int"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicLoadWrongMemorySemanticsType) {
|
||||
@@ -641,6 +641,19 @@ OpAtomicStore %f32vec4_var %device %relaxed %f32_1
|
||||
"type"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageTypeForOpenCL) {
|
||||
const std::string body = R"(
|
||||
OpAtomicStore %f32_im_var %device %relaxed %f32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateKernelCode(body));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("AtomicStore: storage class must be Function, Workgroup, "
|
||||
"CrossWorkGroup or Generic in the OpenCL environment."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicStoreWrongPointerStorageType) {
|
||||
const std::string body = R"(
|
||||
OpAtomicStore %f32_uc_var %device %relaxed %f32_1
|
||||
@@ -648,11 +661,9 @@ OpAtomicStore %f32_uc_var %device %relaxed %f32_1
|
||||
|
||||
CompileSuccessfully(GenerateKernelCode(body));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("AtomicStore: expected Pointer Storage Class to be Uniform, "
|
||||
"Workgroup, CrossWorkgroup, Generic, AtomicCounter, Image or "
|
||||
"StorageBuffer"));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicStore: storage class forbidden by universal "
|
||||
"validation rules."));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicStoreWrongScopeType) {
|
||||
@@ -778,9 +789,7 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"AtomicExchange: expected Memory Scope to be a 32-bit int\n %40 = "
|
||||
"OpAtomicExchange %float %28 %float_1 %uint_0_1 %float_0\n"));
|
||||
HasSubstr("AtomicExchange: expected Memory Scope to be a 32-bit int"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicExchangeWrongMemorySemanticsType) {
|
||||
@@ -895,8 +904,7 @@ OpAtomicStore %f32_var %device %relaxed %f32_1
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("AtomicCompareExchange: expected Memory Scope to be a 32-bit "
|
||||
"int\n %40 = OpAtomicCompareExchange %float %28 %float_1 "
|
||||
"%uint_0_1 %uint_0_1 %float_0 %float_0\n"));
|
||||
"int"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicCompareExchangeWrongMemorySemanticsType1) {
|
||||
@@ -1077,8 +1085,7 @@ TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongScopeType) {
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"AtomicFlagTestAndSet: expected Memory Scope to be a 32-bit int\n "
|
||||
"%40 = OpAtomicFlagTestAndSet %bool %30 %ulong_1 %uint_0_1\n"));
|
||||
"AtomicFlagTestAndSet: expected Memory Scope to be a 32-bit int"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicFlagTestAndSetWrongMemorySemanticsType) {
|
||||
@@ -1179,8 +1186,7 @@ OpAtomicStore %u32_var %device %relaxed %u32_1
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("AtomicIIncrement: Memory Semantics can have at most "
|
||||
"one of the following bits set: Acquire, Release, "
|
||||
"AcquireRelease or SequentiallyConsistent\n %40 = "
|
||||
"OpAtomicIIncrement %uint %30 %uint_1_0 %uint_6\n"));
|
||||
"AcquireRelease or SequentiallyConsistent"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateAtomics, AtomicUniformMemorySemanticsShader) {
|
||||
|
||||
174
3rdparty/spirv-tools/test/val/val_cfg_test.cpp
vendored
174
3rdparty/spirv-tools/test/val/val_cfg_test.cpp
vendored
@@ -2623,6 +2623,134 @@ OpFunctionEnd
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateCFG, SwitchCaseOrderingBad1) {
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpName %default "default"
|
||||
OpName %other "other"
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 0
|
||||
%undef = OpUndef %int
|
||||
%void_fn = OpTypeFunction %void
|
||||
%func = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpSelectionMerge %merge None
|
||||
OpSwitch %undef %default 0 %other 1 %default
|
||||
%default = OpLabel
|
||||
OpBranch %other
|
||||
%other = OpLabel
|
||||
OpBranch %merge
|
||||
%merge = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Case construct that targets 1[%default] has branches to the "
|
||||
"case construct that targets 2[%other], but does not "
|
||||
"immediately precede it in the OpSwitch's target list"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateCFG, SwitchCaseOrderingBad2) {
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpName %default "default"
|
||||
OpName %other "other"
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 0
|
||||
%undef = OpUndef %int
|
||||
%void_fn = OpTypeFunction %void
|
||||
%func = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpSelectionMerge %merge None
|
||||
OpSwitch %undef %default 0 %default 1 %other
|
||||
%other = OpLabel
|
||||
OpBranch %default
|
||||
%default = OpLabel
|
||||
OpBranch %merge
|
||||
%merge = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Case construct that targets 2[%other] has branches to the "
|
||||
"case construct that targets 1[%default], but does not "
|
||||
"immediately precede it in the OpSwitch's target list"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateCFG, SwitchMultipleDefaultWithFallThroughGood) {
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpName %first "first"
|
||||
OpName %second "second"
|
||||
OpName %third "third"
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 0
|
||||
%undef = OpUndef %int
|
||||
%void_fn = OpTypeFunction %void
|
||||
%func = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpSelectionMerge %merge None
|
||||
OpSwitch %undef %second 0 %first 1 %second 2 %third
|
||||
%first = OpLabel
|
||||
OpBranch %second
|
||||
%second = OpLabel
|
||||
OpBranch %third
|
||||
%third = OpLabel
|
||||
OpBranch %merge
|
||||
%merge = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateCFG, SwitchMultipleDefaultWithFallThroughBad) {
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpName %first "first"
|
||||
OpName %second "second"
|
||||
OpName %third "third"
|
||||
%void = OpTypeVoid
|
||||
%int = OpTypeInt 32 0
|
||||
%undef = OpUndef %int
|
||||
%void_fn = OpTypeFunction %void
|
||||
%func = OpFunction %void None %void_fn
|
||||
%entry = OpLabel
|
||||
OpSelectionMerge %merge None
|
||||
OpSwitch %undef %second 0 %second 1 %first 2 %third
|
||||
%first = OpLabel
|
||||
OpBranch %second
|
||||
%second = OpLabel
|
||||
OpBranch %third
|
||||
%third = OpLabel
|
||||
OpBranch %merge
|
||||
%merge = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateCFG, GoodUnreachableSelection) {
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
@@ -3575,6 +3703,52 @@ OpFunctionEnd
|
||||
"10[%10], but not via a structured exit"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateCFG, ContinueFromNestedSelection) {
|
||||
const std::string text = R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Logical GLSL450
|
||||
%void = OpTypeVoid
|
||||
%void_fn = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%undef = OpUndef %bool
|
||||
%4 = OpFunction %void None %void_fn
|
||||
%5 = OpLabel
|
||||
OpBranch %48
|
||||
%48 = OpLabel
|
||||
OpLoopMerge %47 %50 None
|
||||
OpBranch %10
|
||||
%10 = OpLabel
|
||||
OpLoopMerge %12 %37 None
|
||||
OpBranchConditional %undef %11 %12
|
||||
%11 = OpLabel
|
||||
OpSelectionMerge %31 None
|
||||
OpBranchConditional %undef %30 %31
|
||||
%30 = OpLabel
|
||||
OpSelectionMerge %37 None
|
||||
OpBranchConditional %undef %36 %37
|
||||
%36 = OpLabel
|
||||
OpBranch %37
|
||||
%37 = OpLabel
|
||||
OpBranch %10
|
||||
%31 = OpLabel
|
||||
OpBranch %12
|
||||
%12 = OpLabel
|
||||
OpSelectionMerge %55 None
|
||||
OpBranchConditional %undef %47 %55
|
||||
%55 = OpLabel
|
||||
OpBranch %47
|
||||
%50 = OpLabel
|
||||
OpBranch %48
|
||||
%47 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(text);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
/// TODO(umar): Nested CFG constructs
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -145,10 +145,9 @@ TEST_F(ValidateDerivatives, OpDPdxWrongExecutionModel) {
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"Derivative instructions require Fragment execution model: DPdx"));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Derivative instructions require Fragment or GLCompute "
|
||||
"execution model: DPdx"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -314,7 +314,7 @@ TEST_F(ValidateIdWithMessage, OpDecorationGroupBad) {
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Result id of OpDecorationGroup can only "
|
||||
"be targeted by OpName, OpGroupDecorate, "
|
||||
"OpDecorate, and OpGroupMemberDecorate"));
|
||||
"OpDecorate, OpDecorateId, and OpGroupMemberDecorate"));
|
||||
}
|
||||
TEST_F(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) {
|
||||
std::string spirv = R"(
|
||||
|
||||
185
3rdparty/spirv-tools/test/val/val_image_test.cpp
vendored
185
3rdparty/spirv-tools/test/val/val_image_test.cpp
vendored
@@ -35,6 +35,7 @@ std::string GenerateShaderCode(
|
||||
const std::string& body,
|
||||
const std::string& capabilities_and_extensions = "",
|
||||
const std::string& execution_model = "Fragment",
|
||||
const std::string& execution_mode = "",
|
||||
const spv_target_env env = SPV_ENV_UNIVERSAL_1_0,
|
||||
const std::string& memory_model = "GLSL450") {
|
||||
std::ostringstream ss;
|
||||
@@ -85,6 +86,7 @@ OpCapability ImageBuffer
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
ss << execution_mode;
|
||||
|
||||
if (env == SPV_ENV_VULKAN_1_0) {
|
||||
ss << R"(
|
||||
@@ -606,7 +608,7 @@ TEST_F(ValidateImage, SampledImageVulkanSuccess) {
|
||||
)";
|
||||
|
||||
const spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env), env);
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(env));
|
||||
}
|
||||
|
||||
@@ -658,7 +660,7 @@ TEST_F(ValidateImage, SampledImageVulkanUnknownSampled) {
|
||||
)";
|
||||
|
||||
const spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env), env);
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("Expected Image 'Sampled' parameter to "
|
||||
@@ -847,7 +849,7 @@ TEST_F(ValidateImage, SampleImplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -967,7 +969,7 @@ TEST_F(ValidateImage, SampleExplicitLodSuccessShader) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -1552,7 +1554,7 @@ TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -1686,7 +1688,7 @@ TEST_F(ValidateImage, SampleProjImplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -1807,7 +1809,7 @@ TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -1930,7 +1932,7 @@ TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -2054,7 +2056,7 @@ TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -2177,7 +2179,7 @@ TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -2280,7 +2282,7 @@ TEST_F(ValidateImage, FetchSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -2439,7 +2441,7 @@ TEST_F(ValidateImage, GatherSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -2695,7 +2697,7 @@ TEST_F(ValidateImage, DrefGatherSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -2790,7 +2792,7 @@ TEST_F(ValidateImage, ReadNeedCapabilityStorageImageReadWithoutFormatVulkan) {
|
||||
)";
|
||||
|
||||
spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env).c_str(),
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
|
||||
env);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
@@ -3008,7 +3010,7 @@ TEST_F(ValidateImage, WriteNeedCapabilityStorageImageWriteWithoutFormatVulkan) {
|
||||
)";
|
||||
|
||||
spv_target_env env = SPV_ENV_VULKAN_1_0;
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", env).c_str(),
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env).c_str(),
|
||||
env);
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
|
||||
EXPECT_THAT(
|
||||
@@ -3710,8 +3712,10 @@ TEST_F(ValidateImage, QueryLodWrongExecutionModel) {
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpImageQueryLod requires Fragment execution model"));
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"OpImageQueryLod requires Fragment or GLCompute execution model"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QueryLodWrongExecutionModelWithFunc) {
|
||||
@@ -3729,8 +3733,55 @@ OpFunctionEnd
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"OpImageQueryLod requires Fragment or GLCompute execution model"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QueryLodComputeShaderDerivatives) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
||||
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
|
||||
%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
|
||||
)";
|
||||
|
||||
const std::string extra = R"(
|
||||
OpCapability ComputeDerivativeGroupLinearNV
|
||||
OpExtension "SPV_NV_compute_shader_derivatives"
|
||||
)";
|
||||
const std::string mode = R"(
|
||||
OpExecutionMode %main LocalSize 8 8 1
|
||||
OpExecutionMode %main DerivativeGroupLinearNV
|
||||
)";
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
||||
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
|
||||
%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_hh
|
||||
)";
|
||||
|
||||
const std::string extra = R"(
|
||||
OpCapability ComputeDerivativeGroupLinearNV
|
||||
OpExtension "SPV_NV_compute_shader_derivatives"
|
||||
)";
|
||||
const std::string mode = R"(
|
||||
OpExecutionMode %main LocalSize 8 8 1
|
||||
)";
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpImageQueryLod requires Fragment execution model"));
|
||||
HasSubstr("OpImageQueryLod requires DerivativeGroupQuadsNV or "
|
||||
"DerivativeGroupLinearNV execution mode for GLCompute "
|
||||
"execution model"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
|
||||
@@ -3743,9 +3794,55 @@ TEST_F(ValidateImage, ImplicitLodWrongExecutionModel) {
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body, "", "Vertex").c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("ImplicitLod instructions require Fragment or "
|
||||
"GLCompute execution model"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, ImplicitLodComputeShaderDerivatives) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
||||
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
|
||||
%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
|
||||
)";
|
||||
|
||||
const std::string extra = R"(
|
||||
OpCapability ComputeDerivativeGroupLinearNV
|
||||
OpExtension "SPV_NV_compute_shader_derivatives"
|
||||
)";
|
||||
const std::string mode = R"(
|
||||
OpExecutionMode %main LocalSize 8 8 1
|
||||
OpExecutionMode %main DerivativeGroupLinearNV
|
||||
)";
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, ImplicitLodComputeShaderDerivativesMissingMode) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
||||
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
|
||||
%res1 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh
|
||||
)";
|
||||
|
||||
const std::string extra = R"(
|
||||
OpCapability ComputeDerivativeGroupLinearNV
|
||||
OpExtension "SPV_NV_compute_shader_derivatives"
|
||||
)";
|
||||
const std::string mode = R"(
|
||||
OpExecutionMode %main LocalSize 8 8 1
|
||||
)";
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "GLCompute", mode).c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("ImplicitLod instructions require Fragment execution model"));
|
||||
HasSubstr("ImplicitLod instructions require DerivativeGroupQuadsNV or "
|
||||
"DerivativeGroupLinearNV execution mode for GLCompute "
|
||||
"execution model"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, ReadSubpassDataWrongExecutionModel) {
|
||||
@@ -3779,7 +3876,7 @@ TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -3907,7 +4004,7 @@ TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4001,7 +4098,7 @@ TEST_F(ValidateImage, SparseFetchSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4218,7 +4315,7 @@ TEST_F(ValidateImage, SparseGatherSuccess) {
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4359,7 +4456,7 @@ OpCapability StorageImageReadWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4376,7 +4473,7 @@ OpCapability StorageImageReadWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4395,7 +4492,7 @@ OpCapability StorageImageReadWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
@@ -4417,7 +4514,7 @@ OpCapability StorageImageReadWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
@@ -4438,7 +4535,7 @@ OpCapability StorageImageWriteWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4457,7 +4554,7 @@ OpCapability StorageImageReadWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
@@ -4478,7 +4575,7 @@ OpCapability StorageImageWriteWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
@@ -4499,7 +4596,7 @@ OpCapability StorageImageWriteWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
@@ -4522,7 +4619,7 @@ OpCapability VulkanMemoryModelKHR
|
||||
OpCapability VulkanMemoryModelDeviceScopeKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4539,7 +4636,7 @@ OpCapability StorageImageReadWithoutFormat
|
||||
OpCapability VulkanMemoryModelKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
|
||||
@@ -4562,7 +4659,7 @@ OpCapability VulkanMemoryModelKHR
|
||||
OpCapability VulkanMemoryModelDeviceScopeKHR
|
||||
OpExtension "SPV_KHR_vulkan_memory_model"
|
||||
)";
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment",
|
||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3, "VulkanKHR")
|
||||
.c_str());
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
|
||||
@@ -4609,7 +4706,7 @@ TEST_F(ValidateImage, SignExtendV13Bad) {
|
||||
%res1 = OpImageRead %u32vec4 %img %u32vec2_01 SignExtend
|
||||
)";
|
||||
|
||||
EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment",
|
||||
EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3)),
|
||||
HasSubstr("Invalid image operand 'SignExtend'"));
|
||||
}
|
||||
@@ -4620,7 +4717,7 @@ TEST_F(ValidateImage, ZeroExtendV13Bad) {
|
||||
%res1 = OpImageRead %u32vec4 %img %u32vec2_01 ZeroExtend
|
||||
)";
|
||||
|
||||
EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment",
|
||||
EXPECT_THAT(CompileFailure(GenerateShaderCode(body, "", "Fragment", "",
|
||||
SPV_ENV_UNIVERSAL_1_3)),
|
||||
HasSubstr("Invalid image operand 'ZeroExtend'"));
|
||||
}
|
||||
@@ -4634,7 +4731,7 @@ TEST_F(ValidateImage, SignExtendScalarUIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
@@ -4649,7 +4746,7 @@ TEST_F(ValidateImage, SignExtendScalarSIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
@@ -4663,7 +4760,7 @@ TEST_F(ValidateImage, SignExtendScalarVectorUIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
@@ -4677,7 +4774,7 @@ TEST_F(ValidateImage, SignExtendVectorSIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
@@ -4695,7 +4792,7 @@ TEST_F(ValidateImage, ZeroExtendScalarUIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
@@ -4710,7 +4807,7 @@ TEST_F(ValidateImage, ZeroExtendScalarSIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
@@ -4724,7 +4821,7 @@ TEST_F(ValidateImage, ZeroExtendScalarVectorUIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
@@ -4738,7 +4835,7 @@ TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) {
|
||||
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
|
||||
|
||||
CompileSuccessfully(
|
||||
GenerateShaderCode(body, extra, "Fragment", SPV_ENV_UNIVERSAL_1_4),
|
||||
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_4),
|
||||
SPV_ENV_UNIVERSAL_1_4);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
current directory. Optionally insert them. When inserting, replaces
|
||||
an MIT or Khronos free use license with Apache 2.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import fileinput
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
# limitations under the License.
|
||||
"""Checks names of global exports from a library."""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os.path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
# limitations under the License.
|
||||
"""Generates various info tables from SPIR-V JSON grammar."""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import errno
|
||||
import json
|
||||
import os.path
|
||||
@@ -36,8 +34,8 @@ SPV_AMD_shader_trinary_minmax
|
||||
|
||||
|
||||
def make_path_to_file(f):
|
||||
"""Makes all ancestor directories to the given file, if they
|
||||
don't yet exist.
|
||||
"""Makes all ancestor directories to the given file, if they don't yet
|
||||
exist.
|
||||
|
||||
Arguments:
|
||||
f: The file whose ancestor directories are to be created.
|
||||
@@ -53,8 +51,8 @@ def make_path_to_file(f):
|
||||
|
||||
|
||||
def convert_min_required_version(version):
|
||||
"""Converts the minimal required SPIR-V version encoded in the
|
||||
grammar to the symbol in SPIRV-Tools"""
|
||||
"""Converts the minimal required SPIR-V version encoded in the grammar to
|
||||
the symbol in SPIRV-Tools."""
|
||||
if version is None:
|
||||
return 'SPV_SPIRV_VERSION_WORD(1, 0)'
|
||||
if version == 'None':
|
||||
@@ -63,8 +61,8 @@ def convert_min_required_version(version):
|
||||
|
||||
|
||||
def convert_max_required_version(version):
|
||||
"""Converts the maximum required SPIR-V version encoded in the
|
||||
grammar to the symbol in SPIRV-Tools"""
|
||||
"""Converts the maximum required SPIR-V version encoded in the grammar to
|
||||
the symbol in SPIRV-Tools."""
|
||||
if version is None:
|
||||
return '0xffffffffu'
|
||||
return 'SPV_SPIRV_VERSION_WORD({})'.format(version.replace('.', ','))
|
||||
@@ -79,7 +77,7 @@ def compose_capability_list(caps):
|
||||
Returns:
|
||||
a string containing the braced list of SpvCapability* enums named by caps.
|
||||
"""
|
||||
return "{" + ", ".join(['SpvCapability{}'.format(c) for c in caps]) + "}"
|
||||
return '{' + ', '.join(['SpvCapability{}'.format(c) for c in caps]) + '}'
|
||||
|
||||
|
||||
def get_capability_array_name(caps):
|
||||
@@ -116,8 +114,8 @@ def compose_extension_list(exts):
|
||||
Returns:
|
||||
a string containing the braced list of extensions named by exts.
|
||||
"""
|
||||
return "{" + ", ".join(
|
||||
['spvtools::Extension::k{}'.format(e) for e in exts]) + "}"
|
||||
return '{' + ', '.join(
|
||||
['spvtools::Extension::k{}'.format(e) for e in exts]) + '}'
|
||||
|
||||
|
||||
def get_extension_array_name(extensions):
|
||||
@@ -148,8 +146,8 @@ def generate_extension_arrays(extensions):
|
||||
|
||||
|
||||
def convert_operand_kind(operand_tuple):
|
||||
"""Returns the corresponding operand type used in spirv-tools for
|
||||
the given operand kind and quantifier used in the JSON grammar.
|
||||
"""Returns the corresponding operand type used in spirv-tools for the given
|
||||
operand kind and quantifier used in the JSON grammar.
|
||||
|
||||
Arguments:
|
||||
- operand_tuple: a tuple of two elements:
|
||||
@@ -211,8 +209,8 @@ def convert_operand_kind(operand_tuple):
|
||||
|
||||
|
||||
class InstInitializer(object):
|
||||
"""Instances holds a SPIR-V instruction suitable for printing as
|
||||
the initializer for spv_opcode_desc_t."""
|
||||
"""Instances holds a SPIR-V instruction suitable for printing as the
|
||||
initializer for spv_opcode_desc_t."""
|
||||
|
||||
def __init__(self, opname, caps, exts, operands, version, lastVersion):
|
||||
"""Initialization.
|
||||
@@ -244,8 +242,8 @@ class InstInitializer(object):
|
||||
self.lastVersion = convert_max_required_version(lastVersion)
|
||||
|
||||
def fix_syntax(self):
|
||||
"""Fix an instruction's syntax, adjusting for differences between
|
||||
the officially released grammar and how SPIRV-Tools uses the grammar.
|
||||
"""Fix an instruction's syntax, adjusting for differences between the
|
||||
officially released grammar and how SPIRV-Tools uses the grammar.
|
||||
|
||||
Fixes:
|
||||
- ExtInst should not end with SPV_OPERAND_VARIABLE_ID.
|
||||
@@ -337,8 +335,8 @@ def generate_instruction(inst, is_ext_inst):
|
||||
|
||||
|
||||
def generate_instruction_table(inst_table):
|
||||
"""Returns the info table containing all SPIR-V instructions,
|
||||
sorted by opcode, and prefixed by capability arrays.
|
||||
"""Returns the info table containing all SPIR-V instructions, sorted by
|
||||
opcode, and prefixed by capability arrays.
|
||||
|
||||
Note:
|
||||
- the built-in sorted() function is guaranteed to be stable.
|
||||
@@ -435,9 +433,9 @@ def generate_enum_operand_kind_entry(entry, extension_map):
|
||||
value = entry.get('value')
|
||||
caps = entry.get('capabilities', [])
|
||||
if value in extension_map:
|
||||
exts = extension_map[value]
|
||||
exts = extension_map[value]
|
||||
else:
|
||||
exts = []
|
||||
exts = []
|
||||
params = entry.get('parameters', [])
|
||||
params = [p.get('kind') for p in params]
|
||||
params = zip(params, [''] * len(params))
|
||||
@@ -453,8 +451,10 @@ def generate_enum_operand_kind_entry(entry, extension_map):
|
||||
|
||||
def generate_enum_operand_kind(enum, synthetic_exts_list):
|
||||
"""Returns the C definition for the given operand kind.
|
||||
Also appends to |synthetic_exts_list| a list of extension
|
||||
lists used."""
|
||||
|
||||
Also appends to |synthetic_exts_list| a list of extension lists
|
||||
used.
|
||||
"""
|
||||
kind = enum.get('kind')
|
||||
assert kind is not None
|
||||
|
||||
@@ -462,9 +462,9 @@ def generate_enum_operand_kind(enum, synthetic_exts_list):
|
||||
# preserve their order so the first name listed in the grammar
|
||||
# as the preferred name for disassembly.
|
||||
if enum.get('category') == 'ValueEnum':
|
||||
functor = lambda k: (k['value'])
|
||||
def functor(k): return (k['value'])
|
||||
else:
|
||||
functor = lambda k: (int(k['value'], 16))
|
||||
def functor(k): return (int(k['value'], 16))
|
||||
entries = sorted(enum.get('enumerants', []), key=functor)
|
||||
|
||||
# SubgroupEqMask and SubgroupEqMaskKHR are the same number with
|
||||
@@ -472,16 +472,16 @@ def generate_enum_operand_kind(enum, synthetic_exts_list):
|
||||
# does. Both should have the extension list.
|
||||
# So create a mapping from enum value to the union of the extensions
|
||||
# across all those grammar entries. Preserve order.
|
||||
extension_map = { }
|
||||
extension_map = {}
|
||||
for e in entries:
|
||||
value = e.get('value')
|
||||
extension_map[value] = []
|
||||
value = e.get('value')
|
||||
extension_map[value] = []
|
||||
for e in entries:
|
||||
value = e.get('value')
|
||||
exts = e.get('extensions', [])
|
||||
for ext in exts:
|
||||
if ext not in extension_map[value]:
|
||||
extension_map[value].append(ext)
|
||||
value = e.get('value')
|
||||
exts = e.get('extensions', [])
|
||||
for ext in exts:
|
||||
if ext not in extension_map[value]:
|
||||
extension_map[value].append(ext)
|
||||
synthetic_exts_list.extend(extension_map.values())
|
||||
|
||||
name = '{}_{}Entries'.format(PYGEN_VARIABLE_PREFIX, kind)
|
||||
@@ -544,7 +544,8 @@ def get_extension_list(instructions, operand_kinds):
|
||||
|
||||
things_with_an_extensions_field = [item for item in instructions]
|
||||
|
||||
enumerants = sum([item.get('enumerants', []) for item in operand_kinds], [])
|
||||
enumerants = sum([item.get('enumerants', [])
|
||||
for item in operand_kinds], [])
|
||||
|
||||
things_with_an_extensions_field.extend(enumerants)
|
||||
|
||||
@@ -553,11 +554,12 @@ def get_extension_list(instructions, operand_kinds):
|
||||
if item.get('extensions')], [])
|
||||
|
||||
for item in EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split():
|
||||
# If it's already listed in a grammar, then don't put it in the
|
||||
# special exceptions list.
|
||||
assert item not in extensions, "Extension %s is already in a grammar file" % item
|
||||
# If it's already listed in a grammar, then don't put it in the
|
||||
# special exceptions list.
|
||||
assert item not in extensions, 'Extension %s is already in a grammar file' % item
|
||||
|
||||
extensions.extend(EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split())
|
||||
extensions.extend(
|
||||
EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split())
|
||||
|
||||
# Validator would ignore type declaration unique check. Should only be used
|
||||
# for legacy autogenerated test files containing multiple instances of the
|
||||
@@ -570,8 +572,7 @@ def get_extension_list(instructions, operand_kinds):
|
||||
|
||||
def get_capabilities(operand_kinds):
|
||||
"""Returns capabilities as a list of JSON objects, in order of
|
||||
appearance.
|
||||
"""
|
||||
appearance."""
|
||||
enumerants = sum([item.get('enumerants', []) for item in operand_kinds
|
||||
if item.get('kind') in ['Capability']], [])
|
||||
return enumerants
|
||||
@@ -620,6 +621,7 @@ def generate_string_to_extension_mapping(extensions):
|
||||
|
||||
def generate_capability_to_string_mapping(operand_kinds):
|
||||
"""Returns mapping function from capabilities to corresponding strings.
|
||||
|
||||
We take care to avoid emitting duplicate values.
|
||||
"""
|
||||
function = 'const char* CapabilityToString(SpvCapability capability) {\n'
|
||||
@@ -649,8 +651,8 @@ def generate_all_string_enum_mappings(extensions, operand_kinds):
|
||||
|
||||
|
||||
def precondition_operand_kinds(operand_kinds):
|
||||
"""For operand kinds that have the same number, make sure they all have
|
||||
the same extension list"""
|
||||
"""For operand kinds that have the same number, make sure they all have the
|
||||
same extension list."""
|
||||
return operand_kinds
|
||||
|
||||
|
||||
@@ -751,45 +753,47 @@ def main():
|
||||
if args.core_insts_output is not None:
|
||||
make_path_to_file(args.core_insts_output)
|
||||
make_path_to_file(args.operand_kinds_output)
|
||||
print(generate_instruction_table(core_grammar['instructions']),
|
||||
file=open(args.core_insts_output, 'w'))
|
||||
print(generate_operand_kind_table(operand_kinds),
|
||||
file=open(args.operand_kinds_output, 'w'))
|
||||
with open(args.core_insts_output, 'w') as f:
|
||||
f.write(generate_instruction_table(
|
||||
core_grammar['instructions']))
|
||||
with open(args.operand_kinds_output, 'w') as f:
|
||||
f.write(generate_operand_kind_table(operand_kinds))
|
||||
if args.extension_enum_output is not None:
|
||||
make_path_to_file(args.extension_enum_output)
|
||||
print(generate_extension_enum(extensions),
|
||||
file=open(args.extension_enum_output, 'w'))
|
||||
with open(args.extension_enum_output, 'w') as f:
|
||||
f.write(generate_extension_enum(extensions))
|
||||
if args.enum_string_mapping_output is not None:
|
||||
make_path_to_file(args.enum_string_mapping_output)
|
||||
print(generate_all_string_enum_mappings(extensions, operand_kinds),
|
||||
file=open(args.enum_string_mapping_output, 'w'))
|
||||
with open(args.enum_string_mapping_output, 'w') as f:
|
||||
f.write(generate_all_string_enum_mappings(
|
||||
extensions, operand_kinds))
|
||||
|
||||
if args.extinst_glsl_grammar is not None:
|
||||
with open(args.extinst_glsl_grammar) as json_file:
|
||||
grammar = json.loads(json_file.read())
|
||||
make_path_to_file(args.glsl_insts_output)
|
||||
print(generate_extended_instruction_table(
|
||||
grammar['instructions'], "glsl"),
|
||||
file=open(args.glsl_insts_output, 'w'))
|
||||
with open(args.glsl_insts_output, 'w') as f:
|
||||
f.write(generate_extended_instruction_table(
|
||||
grammar['instructions'], 'glsl'))
|
||||
|
||||
if args.extinst_opencl_grammar is not None:
|
||||
with open(args.extinst_opencl_grammar) as json_file:
|
||||
grammar = json.loads(json_file.read())
|
||||
make_path_to_file(args.opencl_insts_output)
|
||||
print(generate_extended_instruction_table(
|
||||
grammar['instructions'], "opencl"),
|
||||
file=open(args.opencl_insts_output, 'w'))
|
||||
with open(args.opencl_insts_output, 'w') as f:
|
||||
f.write(generate_extended_instruction_table(
|
||||
grammar['instructions'], 'opencl'))
|
||||
|
||||
if args.extinst_vendor_grammar is not None:
|
||||
with open(args.extinst_vendor_grammar) as json_file:
|
||||
grammar = json.loads(json_file.read())
|
||||
make_path_to_file(args.vendor_insts_output)
|
||||
name = args.extinst_vendor_grammar
|
||||
start = name.find("extinst.") + len("extinst.")
|
||||
name = name[start:-len(".grammar.json")].replace("-", "_")
|
||||
print(generate_extended_instruction_table(
|
||||
grammar['instructions'], name),
|
||||
file=open(args.vendor_insts_output, 'w'))
|
||||
start = name.find('extinst.') + len('extinst.')
|
||||
name = name[start:-len('.grammar.json')].replace('-', '_')
|
||||
with open(args.vendor_insts_output, 'w') as f:
|
||||
f.write(generate_extended_instruction_table(
|
||||
grammar['instructions'], name))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
# limitations under the License.
|
||||
"""Generates language headers from a JSON grammar file"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import errno
|
||||
import json
|
||||
import os.path
|
||||
@@ -181,7 +179,8 @@ def main():
|
||||
version = grammar_json['version'],
|
||||
revision = grammar_json['revision'])
|
||||
make_path_to_file(args.extinst_output_base)
|
||||
print(CGenerator().generate(grammar), file=open(args.extinst_output_base + '.h', 'w'))
|
||||
with open(args.extinst_output_base + '.h', 'w') as f:
|
||||
f.write(CGenerator().generate(grammar))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
# limitations under the License.
|
||||
"""Generates the vendor tool table from the SPIR-V XML registry."""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import distutils.dir_util
|
||||
import os.path
|
||||
import xml.etree.ElementTree
|
||||
@@ -65,7 +63,8 @@ def main():
|
||||
registry = xml.etree.ElementTree.fromstring(xml_in.read())
|
||||
|
||||
distutils.dir_util.mkpath(os.path.dirname(args.generator_output))
|
||||
print(generate_vendor_table(registry), file=open(args.generator_output, 'w'))
|
||||
with open(args.generator_output, 'w') as f:
|
||||
f.write(generate_vendor_table(registry))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
# limitations under the License.
|
||||
"""Generates Vim syntax rules for SPIR-V assembly (.spvasm) files"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import json
|
||||
|
||||
PREAMBLE="""" Vim syntax file
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
# "unknown hash".
|
||||
# The string contents are escaped as necessary.
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import datetime
|
||||
import errno
|
||||
import os
|
||||
|
||||
Reference in New Issue
Block a user