Updated spirv-tools.

This commit is contained in:
Бранимир Караџић
2019-07-24 20:24:36 -07:00
parent 651f4c3e34
commit eabaa485af
45 changed files with 924 additions and 337 deletions

View File

@@ -134,4 +134,4 @@ enum DebugInfoDebugOperation {
}
#endif
#endif // SPIRV_EXTINST_DebugInfo_H_
#endif // SPIRV_EXTINST_DebugInfo_H_

View File

@@ -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"

View File

@@ -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}
};
};

View File

@@ -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}}
};
};

View File

@@ -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 "";
}
}

View File

@@ -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

View File

@@ -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"},

View File

@@ -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}}
};
};

View File

@@ -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}}
};
};

View File

@@ -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}
};
};

View File

@@ -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}}
};
};

View File

@@ -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}}
};
};

View File

@@ -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}}
};
};

View File

@@ -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}}
};
};

View File

@@ -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();

View File

@@ -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,

View File

@@ -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_;

View File

@@ -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,

View File

@@ -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|.

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 ||

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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"(

View File

@@ -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(""));

View File

@@ -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

View File

@@ -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

View File

@@ -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__':

View File

@@ -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__':

View File

@@ -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__':

View File

@@ -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

View 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