Updated spirv-tools.

This commit is contained in:
Бранимир Караџић 2024-06-15 10:33:35 -07:00
parent 2ca2bbc20e
commit ba632e83b8
40 changed files with 830 additions and 354 deletions

View File

@ -1 +1 @@
"v2024.2", "SPIRV-Tools v2024.2 v2024.2.rc1-12-g1e0a7201" "v2024.2", "SPIRV-Tools v2024.2 v2024.2.rc1-28-gf2bbb12a"

View File

@ -62,6 +62,7 @@ static const spv::Capability pygen_variable_caps_RayTracingMotionBlurNV[] = {spv
static const spv::Capability pygen_variable_caps_RayTracingNV[] = {spv::Capability::RayTracingNV}; static const spv::Capability pygen_variable_caps_RayTracingNV[] = {spv::Capability::RayTracingNV};
static const spv::Capability pygen_variable_caps_RayTracingNVRayTracingKHR[] = {spv::Capability::RayTracingNV, spv::Capability::RayTracingKHR}; static const spv::Capability pygen_variable_caps_RayTracingNVRayTracingKHR[] = {spv::Capability::RayTracingNV, spv::Capability::RayTracingKHR};
static const spv::Capability pygen_variable_caps_RayTracingNVRayTracingKHRRayQueryKHR[] = {spv::Capability::RayTracingNV, spv::Capability::RayTracingKHR, spv::Capability::RayQueryKHR}; static const spv::Capability pygen_variable_caps_RayTracingNVRayTracingKHRRayQueryKHR[] = {spv::Capability::RayTracingNV, spv::Capability::RayTracingKHR, spv::Capability::RayQueryKHR};
static const spv::Capability pygen_variable_caps_ReplicatedCompositesEXT[] = {spv::Capability::ReplicatedCompositesEXT};
static const spv::Capability pygen_variable_caps_Shader[] = {spv::Capability::Shader}; static const spv::Capability pygen_variable_caps_Shader[] = {spv::Capability::Shader};
static const spv::Capability pygen_variable_caps_ShaderBitInstructions[] = {spv::Capability::Shader, spv::Capability::BitInstructions}; static const spv::Capability pygen_variable_caps_ShaderBitInstructions[] = {spv::Capability::Shader, spv::Capability::BitInstructions};
static const spv::Capability pygen_variable_caps_ShaderClockKHR[] = {spv::Capability::ShaderClockKHR}; static const spv::Capability pygen_variable_caps_ShaderClockKHR[] = {spv::Capability::ShaderClockKHR};
@ -109,6 +110,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_integer_dot_product
static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_query}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_query};
static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing};
static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracingSPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_tracing, spvtools::Extension::kSPV_KHR_ray_query}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracingSPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_tracing, spvtools::Extension::kSPV_KHR_ray_query};
static const spvtools::Extension pygen_variable_exts_SPV_KHR_relaxed_extended_instruction[] = {spvtools::Extension::kSPV_KHR_relaxed_extended_instruction};
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_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
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_KHR_subgroup_vote[] = {spvtools::Extension::kSPV_KHR_subgroup_vote};
static const spvtools::Extension pygen_variable_exts_SPV_KHR_terminate_invocation[] = {spvtools::Extension::kSPV_KHR_terminate_invocation}; static const spvtools::Extension pygen_variable_exts_SPV_KHR_terminate_invocation[] = {spvtools::Extension::kSPV_KHR_terminate_invocation};
@ -477,6 +479,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
{"SubgroupAllEqualKHR", spv::Op::OpSubgroupAllEqualKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu, 0xffffffffu}, {"SubgroupAllEqualKHR", spv::Op::OpSubgroupAllEqualKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu, 0xffffffffu},
{"GroupNonUniformRotateKHR", spv::Op::OpGroupNonUniformRotateKHR, 1, pygen_variable_caps_GroupNonUniformRotateKHR, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}, {"GroupNonUniformRotateKHR", spv::Op::OpGroupNonUniformRotateKHR, 1, pygen_variable_caps_GroupNonUniformRotateKHR, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"SubgroupReadInvocationKHR", spv::Op::OpSubgroupReadInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 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_KHR_shader_ballot, 0xffffffffu, 0xffffffffu}, {"SubgroupReadInvocationKHR", spv::Op::OpSubgroupReadInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 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_KHR_shader_ballot, 0xffffffffu, 0xffffffffu},
{"ExtInstWithForwardRefsKHR", spv::Op::OpExtInstWithForwardRefsKHR, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_relaxed_extended_instruction, 0xffffffffu, 0xffffffffu},
{"TraceRayKHR", spv::Op::OpTraceRayKHR, 1, pygen_variable_caps_RayTracingKHR, 11, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, {"TraceRayKHR", spv::Op::OpTraceRayKHR, 1, pygen_variable_caps_RayTracingKHR, 11, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu},
{"ExecuteCallableKHR", spv::Op::OpExecuteCallableKHR, 1, pygen_variable_caps_RayTracingKHR, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu}, {"ExecuteCallableKHR", spv::Op::OpExecuteCallableKHR, 1, pygen_variable_caps_RayTracingKHR, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu},
{"ConvertUToAccelerationStructureKHR", spv::Op::OpConvertUToAccelerationStructureKHR, 2, pygen_variable_caps_RayTracingKHRRayQueryKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, {"ConvertUToAccelerationStructureKHR", spv::Op::OpConvertUToAccelerationStructureKHR, 2, pygen_variable_caps_RayTracingKHRRayQueryKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
@ -499,6 +502,9 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
{"CooperativeMatrixStoreKHR", spv::Op::OpCooperativeMatrixStoreKHR, 1, pygen_variable_caps_CooperativeMatrixKHR, 5, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu}, {"CooperativeMatrixStoreKHR", spv::Op::OpCooperativeMatrixStoreKHR, 1, pygen_variable_caps_CooperativeMatrixKHR, 5, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"CooperativeMatrixMulAddKHR", spv::Op::OpCooperativeMatrixMulAddKHR, 1, pygen_variable_caps_CooperativeMatrixKHR, 6, {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_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}, {"CooperativeMatrixMulAddKHR", spv::Op::OpCooperativeMatrixMulAddKHR, 1, pygen_variable_caps_CooperativeMatrixKHR, 6, {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_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"CooperativeMatrixLengthKHR", spv::Op::OpCooperativeMatrixLengthKHR, 1, pygen_variable_caps_CooperativeMatrixKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu}, {"CooperativeMatrixLengthKHR", spv::Op::OpCooperativeMatrixLengthKHR, 1, pygen_variable_caps_CooperativeMatrixKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"ConstantCompositeReplicateEXT", spv::Op::OpConstantCompositeReplicateEXT, 1, pygen_variable_caps_ReplicatedCompositesEXT, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"SpecConstantCompositeReplicateEXT", spv::Op::OpSpecConstantCompositeReplicateEXT, 1, pygen_variable_caps_ReplicatedCompositesEXT, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"CompositeConstructReplicateEXT", spv::Op::OpCompositeConstructReplicateEXT, 1, pygen_variable_caps_ReplicatedCompositesEXT, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"TypeRayQueryKHR", spv::Op::OpTypeRayQueryKHR, 1, pygen_variable_caps_RayQueryKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, {"TypeRayQueryKHR", spv::Op::OpTypeRayQueryKHR, 1, pygen_variable_caps_RayQueryKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
{"RayQueryInitializeKHR", spv::Op::OpRayQueryInitializeKHR, 1, pygen_variable_caps_RayQueryKHR, 8, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, {"RayQueryInitializeKHR", spv::Op::OpRayQueryInitializeKHR, 1, pygen_variable_caps_RayQueryKHR, 8, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
{"RayQueryTerminateKHR", spv::Op::OpRayQueryTerminateKHR, 1, pygen_variable_caps_RayQueryKHR, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu}, {"RayQueryTerminateKHR", spv::Op::OpRayQueryTerminateKHR, 1, pygen_variable_caps_RayQueryKHR, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},

File diff suppressed because one or more lines are too long

View File

@ -10,6 +10,7 @@ kSPV_AMD_shader_fragment_mask,
kSPV_AMD_shader_image_load_store_lod, kSPV_AMD_shader_image_load_store_lod,
kSPV_AMD_shader_trinary_minmax, kSPV_AMD_shader_trinary_minmax,
kSPV_AMD_texture_gather_bias_lod, kSPV_AMD_texture_gather_bias_lod,
kSPV_ARM_cooperative_matrix_layouts,
kSPV_ARM_core_builtins, kSPV_ARM_core_builtins,
kSPV_EXT_demote_to_helper_invocation, kSPV_EXT_demote_to_helper_invocation,
kSPV_EXT_descriptor_indexing, kSPV_EXT_descriptor_indexing,
@ -19,6 +20,7 @@ kSPV_EXT_fragment_shader_interlock,
kSPV_EXT_mesh_shader, kSPV_EXT_mesh_shader,
kSPV_EXT_opacity_micromap, kSPV_EXT_opacity_micromap,
kSPV_EXT_physical_storage_buffer, kSPV_EXT_physical_storage_buffer,
kSPV_EXT_replicated_composites,
kSPV_EXT_shader_atomic_float16_add, kSPV_EXT_shader_atomic_float16_add,
kSPV_EXT_shader_atomic_float_add, kSPV_EXT_shader_atomic_float_add,
kSPV_EXT_shader_atomic_float_min_max, kSPV_EXT_shader_atomic_float_min_max,
@ -94,6 +96,7 @@ kSPV_KHR_ray_cull_mask,
kSPV_KHR_ray_query, kSPV_KHR_ray_query,
kSPV_KHR_ray_tracing, kSPV_KHR_ray_tracing,
kSPV_KHR_ray_tracing_position_fetch, kSPV_KHR_ray_tracing_position_fetch,
kSPV_KHR_relaxed_extended_instruction,
kSPV_KHR_shader_atomic_counter_ops, kSPV_KHR_shader_atomic_counter_ops,
kSPV_KHR_shader_ballot, kSPV_KHR_shader_ballot,
kSPV_KHR_shader_clock, kSPV_KHR_shader_clock,

View File

@ -152,6 +152,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_explicit_ver
static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_fragment_mask[] = {spvtools::Extension::kSPV_AMD_shader_fragment_mask}; static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_fragment_mask[] = {spvtools::Extension::kSPV_AMD_shader_fragment_mask};
static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_image_load_store_lod[] = {spvtools::Extension::kSPV_AMD_shader_image_load_store_lod}; static const spvtools::Extension pygen_variable_exts_SPV_AMD_shader_image_load_store_lod[] = {spvtools::Extension::kSPV_AMD_shader_image_load_store_lod};
static const spvtools::Extension pygen_variable_exts_SPV_AMD_texture_gather_bias_lod[] = {spvtools::Extension::kSPV_AMD_texture_gather_bias_lod}; static const spvtools::Extension pygen_variable_exts_SPV_AMD_texture_gather_bias_lod[] = {spvtools::Extension::kSPV_AMD_texture_gather_bias_lod};
static const spvtools::Extension pygen_variable_exts_SPV_ARM_cooperative_matrix_layouts[] = {spvtools::Extension::kSPV_ARM_cooperative_matrix_layouts};
static const spvtools::Extension pygen_variable_exts_SPV_ARM_core_builtins[] = {spvtools::Extension::kSPV_ARM_core_builtins}; static const spvtools::Extension pygen_variable_exts_SPV_ARM_core_builtins[] = {spvtools::Extension::kSPV_ARM_core_builtins};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_demote_to_helper_invocation[] = {spvtools::Extension::kSPV_EXT_demote_to_helper_invocation}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_demote_to_helper_invocation[] = {spvtools::Extension::kSPV_EXT_demote_to_helper_invocation};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_descriptor_indexing[] = {spvtools::Extension::kSPV_EXT_descriptor_indexing}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_descriptor_indexing[] = {spvtools::Extension::kSPV_EXT_descriptor_indexing};
@ -163,6 +164,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_EXT_mesh_shaderSPV_KHR_
static const spvtools::Extension pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_EXT_mesh_shader, spvtools::Extension::kSPV_NV_mesh_shader}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_EXT_mesh_shader, spvtools::Extension::kSPV_NV_mesh_shader};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_opacity_micromap[] = {spvtools::Extension::kSPV_EXT_opacity_micromap}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_opacity_micromap[] = {spvtools::Extension::kSPV_EXT_opacity_micromap};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer[] = {spvtools::Extension::kSPV_EXT_physical_storage_buffer, spvtools::Extension::kSPV_KHR_physical_storage_buffer}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer[] = {spvtools::Extension::kSPV_EXT_physical_storage_buffer, spvtools::Extension::kSPV_KHR_physical_storage_buffer};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_replicated_composites[] = {spvtools::Extension::kSPV_EXT_replicated_composites};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float16_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float16_add}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float16_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float16_add};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_add}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_add[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_add};
static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_min_max[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_min_max}; static const spvtools::Extension pygen_variable_exts_SPV_EXT_shader_atomic_float_min_max[] = {spvtools::Extension::kSPV_EXT_shader_atomic_float_min_max};
@ -444,18 +446,18 @@ static const spv_operand_desc_t pygen_variable_ExecutionModelEntries[] = {
{"Kernel", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,0), 0xffffffffu}, {"Kernel", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,0), 0xffffffffu},
{"TaskNV", 5267, 1, pygen_variable_caps_MeshShadingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"TaskNV", 5267, 1, pygen_variable_caps_MeshShadingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"MeshNV", 5268, 1, pygen_variable_caps_MeshShadingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"MeshNV", 5268, 1, pygen_variable_caps_MeshShadingNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"RayGenerationNV", 5313, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"RayGenerationKHR", 5313, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"RayGenerationKHR", 5313, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"IntersectionNV", 5314, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"RayGenerationNV", 5313, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"IntersectionKHR", 5314, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"IntersectionKHR", 5314, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"AnyHitNV", 5315, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"IntersectionNV", 5314, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"AnyHitKHR", 5315, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"AnyHitKHR", 5315, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"ClosestHitNV", 5316, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"AnyHitNV", 5315, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"ClosestHitKHR", 5316, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"ClosestHitKHR", 5316, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"MissNV", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"ClosestHitNV", 5316, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"MissKHR", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"MissKHR", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"CallableNV", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"MissNV", 5317, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"CallableKHR", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"CallableKHR", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"CallableNV", 5318, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"TaskEXT", 5364, 1, pygen_variable_caps_MeshShadingEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"TaskEXT", 5364, 1, pygen_variable_caps_MeshShadingEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"MeshEXT", 5365, 1, pygen_variable_caps_MeshShadingEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu} {"MeshEXT", 5365, 1, pygen_variable_caps_MeshShadingEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
}; };
@ -540,14 +542,14 @@ static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = {
{"StencilRefLessBackAMD", 5084, 1, pygen_variable_caps_StencilExportEXT, 2, pygen_variable_exts_SPV_AMD_shader_early_and_late_fragment_testsSPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu}, {"StencilRefLessBackAMD", 5084, 1, pygen_variable_caps_StencilExportEXT, 2, pygen_variable_exts_SPV_AMD_shader_early_and_late_fragment_testsSPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu},
{"QuadDerivativesKHR", 5088, 1, pygen_variable_caps_QuadControlKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"QuadDerivativesKHR", 5088, 1, pygen_variable_caps_QuadControlKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"RequireFullQuadsKHR", 5089, 1, pygen_variable_caps_QuadControlKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"RequireFullQuadsKHR", 5089, 1, pygen_variable_caps_QuadControlKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"OutputLinesNV", 5269, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"OutputLinesEXT", 5269, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"OutputLinesEXT", 5269, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"OutputPrimitivesNV", 5270, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}, {"OutputLinesNV", 5269, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"OutputPrimitivesEXT", 5270, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}, {"OutputPrimitivesEXT", 5270, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
{"OutputPrimitivesNV", 5270, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
{"DerivativeGroupQuadsNV", 5289, 1, pygen_variable_caps_ComputeDerivativeGroupQuadsNV, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu}, {"DerivativeGroupQuadsNV", 5289, 1, pygen_variable_caps_ComputeDerivativeGroupQuadsNV, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu},
{"DerivativeGroupLinearNV", 5290, 1, pygen_variable_caps_ComputeDerivativeGroupLinearNV, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu}, {"DerivativeGroupLinearNV", 5290, 1, pygen_variable_caps_ComputeDerivativeGroupLinearNV, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu},
{"OutputTrianglesNV", 5298, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"OutputTrianglesEXT", 5298, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"OutputTrianglesEXT", 5298, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"OutputTrianglesNV", 5298, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"PixelInterlockOrderedEXT", 5366, 1, pygen_variable_caps_FragmentShaderPixelInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, {"PixelInterlockOrderedEXT", 5366, 1, pygen_variable_caps_FragmentShaderPixelInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
{"PixelInterlockUnorderedEXT", 5367, 1, pygen_variable_caps_FragmentShaderPixelInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, {"PixelInterlockUnorderedEXT", 5367, 1, pygen_variable_caps_FragmentShaderPixelInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
{"SampleInterlockOrderedEXT", 5368, 1, pygen_variable_caps_FragmentShaderSampleInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu}, {"SampleInterlockOrderedEXT", 5368, 1, pygen_variable_caps_FragmentShaderSampleInterlockEXT, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
@ -591,18 +593,18 @@ static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = {
{"TileImageEXT", 4172, 1, pygen_variable_caps_TileImageColorReadAccessEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"TileImageEXT", 4172, 1, pygen_variable_caps_TileImageColorReadAccessEXT, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"NodePayloadAMDX", 5068, 1, pygen_variable_caps_ShaderEnqueueAMDX, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"NodePayloadAMDX", 5068, 1, pygen_variable_caps_ShaderEnqueueAMDX, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"NodeOutputPayloadAMDX", 5076, 1, pygen_variable_caps_ShaderEnqueueAMDX, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"NodeOutputPayloadAMDX", 5076, 1, pygen_variable_caps_ShaderEnqueueAMDX, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"CallableDataNV", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"CallableDataKHR", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"CallableDataKHR", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"IncomingCallableDataNV", 5329, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"CallableDataNV", 5328, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"IncomingCallableDataKHR", 5329, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"IncomingCallableDataKHR", 5329, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"RayPayloadNV", 5338, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"IncomingCallableDataNV", 5329, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"RayPayloadKHR", 5338, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"RayPayloadKHR", 5338, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"HitAttributeNV", 5339, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"RayPayloadNV", 5338, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"HitAttributeKHR", 5339, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"HitAttributeKHR", 5339, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"IncomingRayPayloadNV", 5342, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"HitAttributeNV", 5339, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"IncomingRayPayloadKHR", 5342, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"IncomingRayPayloadKHR", 5342, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ShaderRecordBufferNV", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"IncomingRayPayloadNV", 5342, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ShaderRecordBufferKHR", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"ShaderRecordBufferKHR", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ShaderRecordBufferNV", 5343, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"PhysicalStorageBuffer", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"PhysicalStorageBuffer", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
{"PhysicalStorageBufferEXT", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu}, {"PhysicalStorageBufferEXT", 5349, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
{"HitObjectAttributeNV", 5385, 1, pygen_variable_caps_ShaderInvocationReorderNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"HitObjectAttributeNV", 5385, 1, pygen_variable_caps_ShaderInvocationReorderNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
@ -854,8 +856,8 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
{"PassthroughNV", 5250, 1, pygen_variable_caps_GeometryShaderPassthroughNV, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu, 0xffffffffu}, {"PassthroughNV", 5250, 1, pygen_variable_caps_GeometryShaderPassthroughNV, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu, 0xffffffffu},
{"ViewportRelativeNV", 5252, 1, pygen_variable_caps_ShaderViewportMaskNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"ViewportRelativeNV", 5252, 1, pygen_variable_caps_ShaderViewportMaskNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"SecondaryViewportRelativeNV", 5256, 1, pygen_variable_caps_ShaderStereoViewNV, 1, pygen_variable_exts_SPV_NV_stereo_view_rendering, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu}, {"SecondaryViewportRelativeNV", 5256, 1, pygen_variable_caps_ShaderStereoViewNV, 1, pygen_variable_exts_SPV_NV_stereo_view_rendering, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
{"PerPrimitiveNV", 5271, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"PerPrimitiveEXT", 5271, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PerPrimitiveEXT", 5271, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"PerPrimitiveNV", 5271, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"PerViewNV", 5272, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PerViewNV", 5272, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"PerTaskNV", 5273, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PerTaskNV", 5273, 2, pygen_variable_caps_MeshShadingNVMeshShadingEXT, 2, pygen_variable_exts_SPV_EXT_mesh_shaderSPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"PerVertexKHR", 5285, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu}, {"PerVertexKHR", 5285, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
@ -1040,37 +1042,37 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
{"PrimitiveLineIndicesEXT", 5295, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PrimitiveLineIndicesEXT", 5295, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"PrimitiveTriangleIndicesEXT", 5296, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"PrimitiveTriangleIndicesEXT", 5296, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"CullPrimitiveEXT", 5299, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu}, {"CullPrimitiveEXT", 5299, 1, pygen_variable_caps_MeshShadingEXT, 1, pygen_variable_exts_SPV_EXT_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
{"LaunchIdNV", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"LaunchIdKHR", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"LaunchIdKHR", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"LaunchSizeNV", 5320, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"LaunchIdNV", 5319, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"LaunchSizeKHR", 5320, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"LaunchSizeKHR", 5320, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WorldRayOriginNV", 5321, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"LaunchSizeNV", 5320, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WorldRayOriginKHR", 5321, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"WorldRayOriginKHR", 5321, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WorldRayDirectionNV", 5322, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"WorldRayOriginNV", 5321, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WorldRayDirectionKHR", 5322, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"WorldRayDirectionKHR", 5322, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ObjectRayOriginNV", 5323, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"WorldRayDirectionNV", 5322, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ObjectRayOriginKHR", 5323, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"ObjectRayOriginKHR", 5323, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ObjectRayDirectionNV", 5324, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"ObjectRayOriginNV", 5323, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ObjectRayDirectionKHR", 5324, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"ObjectRayDirectionKHR", 5324, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"RayTminNV", 5325, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"ObjectRayDirectionNV", 5324, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"RayTminKHR", 5325, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"RayTminKHR", 5325, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"RayTmaxNV", 5326, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"RayTminNV", 5325, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"RayTmaxKHR", 5326, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"RayTmaxKHR", 5326, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"InstanceCustomIndexNV", 5327, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"RayTmaxNV", 5326, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"InstanceCustomIndexKHR", 5327, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"InstanceCustomIndexKHR", 5327, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ObjectToWorldNV", 5330, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"InstanceCustomIndexNV", 5327, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"ObjectToWorldKHR", 5330, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"ObjectToWorldKHR", 5330, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WorldToObjectNV", 5331, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"ObjectToWorldNV", 5330, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WorldToObjectKHR", 5331, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"WorldToObjectKHR", 5331, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WorldToObjectNV", 5331, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"HitTNV", 5332, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"HitTNV", 5332, 1, pygen_variable_caps_RayTracingNV, 1, pygen_variable_exts_SPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"HitKindNV", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"HitKindKHR", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"HitKindKHR", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"HitKindNV", 5333, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"CurrentRayTimeNV", 5334, 1, pygen_variable_caps_RayTracingMotionBlurNV, 1, pygen_variable_exts_SPV_NV_ray_tracing_motion_blur, {}, 0xffffffffu, 0xffffffffu}, {"CurrentRayTimeNV", 5334, 1, pygen_variable_caps_RayTracingMotionBlurNV, 1, pygen_variable_exts_SPV_NV_ray_tracing_motion_blur, {}, 0xffffffffu, 0xffffffffu},
{"HitTriangleVertexPositionsKHR", 5335, 1, pygen_variable_caps_RayTracingPositionFetchKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"HitTriangleVertexPositionsKHR", 5335, 1, pygen_variable_caps_RayTracingPositionFetchKHR, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"HitMicroTriangleVertexPositionsNV", 5337, 1, pygen_variable_caps_RayTracingDisplacementMicromapNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"HitMicroTriangleVertexPositionsNV", 5337, 1, pygen_variable_caps_RayTracingDisplacementMicromapNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"HitMicroTriangleVertexBarycentricsNV", 5344, 1, pygen_variable_caps_RayTracingDisplacementMicromapNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"HitMicroTriangleVertexBarycentricsNV", 5344, 1, pygen_variable_caps_RayTracingDisplacementMicromapNV, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"IncomingRayFlagsNV", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"IncomingRayFlagsKHR", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"IncomingRayFlagsKHR", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"IncomingRayFlagsNV", 5351, 2, pygen_variable_caps_RayTracingNVRayTracingKHR, 2, pygen_variable_exts_SPV_KHR_ray_tracingSPV_NV_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"RayGeometryIndexKHR", 5352, 1, pygen_variable_caps_RayTracingKHR, 1, pygen_variable_exts_SPV_KHR_ray_tracing, {}, 0xffffffffu, 0xffffffffu}, {"RayGeometryIndexKHR", 5352, 1, pygen_variable_caps_RayTracingKHR, 1, pygen_variable_exts_SPV_KHR_ray_tracing, {}, 0xffffffffu, 0xffffffffu},
{"WarpsPerSMNV", 5374, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu}, {"WarpsPerSMNV", 5374, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu},
{"SMCountNV", 5375, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu}, {"SMCountNV", 5375, 1, pygen_variable_caps_ShaderSMBuiltinsNV, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu},
@ -1183,6 +1185,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
{"TileImageColorReadAccessEXT", 4166, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu}, {"TileImageColorReadAccessEXT", 4166, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu},
{"TileImageDepthReadAccessEXT", 4167, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu}, {"TileImageDepthReadAccessEXT", 4167, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu},
{"TileImageStencilReadAccessEXT", 4168, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu}, {"TileImageStencilReadAccessEXT", 4168, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_tile_image, {}, 0xffffffffu, 0xffffffffu},
{"CooperativeMatrixLayoutsARM", 4201, 0, nullptr, 1, pygen_variable_exts_SPV_ARM_cooperative_matrix_layouts, {}, 0xffffffffu, 0xffffffffu},
{"FragmentShadingRateKHR", 4422, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu}, {"FragmentShadingRateKHR", 4422, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu},
{"SubgroupBallotKHR", 4423, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, 0xffffffffu, 0xffffffffu}, {"SubgroupBallotKHR", 4423, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, 0xffffffffu, 0xffffffffu},
{"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu}, {"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
@ -1346,6 +1349,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
{"DotProductKHR", 6019, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu}, {"DotProductKHR", 6019, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
{"RayCullMaskKHR", 6020, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_ray_cull_mask, {}, 0xffffffffu, 0xffffffffu}, {"RayCullMaskKHR", 6020, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_ray_cull_mask, {}, 0xffffffffu, 0xffffffffu},
{"CooperativeMatrixKHR", 6022, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_cooperative_matrix, {}, 0xffffffffu, 0xffffffffu}, {"CooperativeMatrixKHR", 6022, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_cooperative_matrix, {}, 0xffffffffu, 0xffffffffu},
{"ReplicatedCompositesEXT", 6024, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_replicated_composites, {}, 0xffffffffu, 0xffffffffu},
{"BitInstructions", 6025, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_bit_instructions, {}, 0xffffffffu, 0xffffffffu}, {"BitInstructions", 6025, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_bit_instructions, {}, 0xffffffffu, 0xffffffffu},
{"GroupNonUniformRotateKHR", 6026, 1, pygen_variable_caps_GroupNonUniform, 1, pygen_variable_exts_SPV_KHR_subgroup_rotate, {}, 0xffffffffu, 0xffffffffu}, {"GroupNonUniformRotateKHR", 6026, 1, pygen_variable_caps_GroupNonUniform, 1, pygen_variable_exts_SPV_KHR_subgroup_rotate, {}, 0xffffffffu, 0xffffffffu},
{"FloatControls2", 6029, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_float_controls2, {}, 0xffffffffu, 0xffffffffu}, {"FloatControls2", 6029, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_float_controls2, {}, 0xffffffffu, 0xffffffffu},
@ -1402,7 +1406,9 @@ static const spv_operand_desc_t pygen_variable_CooperativeMatrixOperandsEntries[
static const spv_operand_desc_t pygen_variable_CooperativeMatrixLayoutEntries[] = { static const spv_operand_desc_t pygen_variable_CooperativeMatrixLayoutEntries[] = {
{"RowMajorKHR", 0, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}, {"RowMajorKHR", 0, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"ColumnMajorKHR", 1, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu} {"ColumnMajorKHR", 1, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"RowBlockedInterleavedARM", 4202, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"ColumnBlockedInterleavedARM", 4203, 0, nullptr, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
}; };
static const spv_operand_desc_t pygen_variable_CooperativeMatrixUseEntries[] = { static const spv_operand_desc_t pygen_variable_CooperativeMatrixUseEntries[] = {

View File

@ -856,6 +856,12 @@ Optimizer::PassToken CreateAmdExtToKhrPass();
// propagated into their final positions. // propagated into their final positions.
Optimizer::PassToken CreateInterpolateFixupPass(); Optimizer::PassToken CreateInterpolateFixupPass();
// Replace OpExtInst instructions with OpExtInstWithForwardRefsKHR when
// the instruction contains a forward reference to another debug instuction.
// Replace OpExtInstWithForwardRefsKHR with OpExtInst when there are no forward
// reference to another debug instruction.
Optimizer::PassToken CreateOpExtInstWithForwardReferenceFixupPass();
// Removes unused components from composite input variables. Current // Removes unused components from composite input variables. Current
// implementation just removes trailing unused components from input arrays // implementation just removes trailing unused components from input arrays
// and structs. The pass performs best after maximizing dead code removal. // and structs. The pass performs best after maximizing dead code removal.

View File

@ -473,7 +473,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0"; if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
parsed_operand.type = SPV_OPERAND_TYPE_ID; parsed_operand.type = SPV_OPERAND_TYPE_ID;
if (opcode == spv::Op::OpExtInst && parsed_operand.offset == 3) { if (spvIsExtendedInstruction(opcode) && parsed_operand.offset == 3) {
// The current word is the extended instruction set Id. // The current word is the extended instruction set Id.
// Set the extended instruction set type for the current instruction. // Set the extended instruction set type for the current instruction.
auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word); auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
@ -494,7 +494,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
break; break;
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: { case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
assert(spv::Op::OpExtInst == opcode); assert(spvIsExtendedInstruction(opcode));
assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE); assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
spv_ext_inst_desc ext_inst; spv_ext_inst_desc ext_inst;
if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) == if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) ==

View File

@ -194,7 +194,27 @@ spv_result_t DisassembleTargetInstruction(
return SPV_SUCCESS; return SPV_SUCCESS;
} }
uint32_t GetLineLengthWithoutColor(const std::string line) {
// Currently, every added color is in the form \x1b...m, so instead of doing a
// lot of string comparisons with spvtools::clr::* strings, we just ignore
// those ranges.
uint32_t length = 0;
for (size_t i = 0; i < line.size(); ++i) {
if (line[i] == '\x1b') {
do {
++i;
} while (line[i] != 'm');
continue;
}
++length;
}
return length;
}
constexpr int kStandardIndent = 15; constexpr int kStandardIndent = 15;
constexpr uint32_t kCommentColumn = 50;
} // namespace } // namespace
namespace disassemble { namespace disassemble {
@ -212,7 +232,8 @@ InstructionDisassembler::InstructionDisassembler(const AssemblyGrammar& grammar,
comment_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COMMENT, options)), comment_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COMMENT, options)),
show_byte_offset_( show_byte_offset_(
spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET, options)), spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET, options)),
name_mapper_(std::move(name_mapper)) {} name_mapper_(std::move(name_mapper)),
last_instruction_comment_alignment_(0) {}
void InstructionDisassembler::EmitHeaderSpirv() { stream_ << "; SPIR-V\n"; } void InstructionDisassembler::EmitHeaderSpirv() { stream_ << "; SPIR-V\n"; }
@ -246,47 +267,119 @@ void InstructionDisassembler::EmitInstruction(
const spv_parsed_instruction_t& inst, size_t inst_byte_offset) { const spv_parsed_instruction_t& inst, size_t inst_byte_offset) {
auto opcode = static_cast<spv::Op>(inst.opcode); auto opcode = static_cast<spv::Op>(inst.opcode);
// To better align the comments (if any), write the instruction to a line
// first so its length can be readily available.
std::ostringstream line;
if (inst.result_id) { if (inst.result_id) {
SetBlue(); SetBlue();
const std::string id_name = name_mapper_(inst.result_id); const std::string id_name = name_mapper_(inst.result_id);
if (indent_) if (indent_)
stream_ << std::setw(std::max(0, indent_ - 3 - int(id_name.size()))); line << std::setw(std::max(0, indent_ - 3 - int(id_name.size())));
stream_ << "%" << id_name; line << "%" << id_name;
ResetColor(); ResetColor();
stream_ << " = "; line << " = ";
} else { } else {
stream_ << std::string(indent_, ' '); line << std::string(indent_, ' ');
} }
stream_ << "Op" << spvOpcodeString(opcode); line << "Op" << spvOpcodeString(opcode);
for (uint16_t i = 0; i < inst.num_operands; i++) { for (uint16_t i = 0; i < inst.num_operands; i++) {
const spv_operand_type_t type = inst.operands[i].type; const spv_operand_type_t type = inst.operands[i].type;
assert(type != SPV_OPERAND_TYPE_NONE); assert(type != SPV_OPERAND_TYPE_NONE);
if (type == SPV_OPERAND_TYPE_RESULT_ID) continue; if (type == SPV_OPERAND_TYPE_RESULT_ID) continue;
stream_ << " "; line << " ";
EmitOperand(inst, i); EmitOperand(line, inst, i);
}
// For the sake of comment generation, store information from some
// instructions for the future.
if (comment_) {
GenerateCommentForDecoratedId(inst);
}
std::ostringstream comments;
const char* comment_separator = "";
if (show_byte_offset_) {
SetGrey(comments);
auto saved_flags = comments.flags();
auto saved_fill = comments.fill();
comments << comment_separator << "0x" << std::setw(8) << std::hex
<< std::setfill('0') << inst_byte_offset;
comments.flags(saved_flags);
comments.fill(saved_fill);
ResetColor(comments);
comment_separator = ", ";
} }
if (comment_ && opcode == spv::Op::OpName) { if (comment_ && opcode == spv::Op::OpName) {
const spv_parsed_operand_t& operand = inst.operands[0]; const spv_parsed_operand_t& operand = inst.operands[0];
const uint32_t word = inst.words[operand.offset]; const uint32_t word = inst.words[operand.offset];
stream_ << " ; id %" << word; comments << comment_separator << "id %" << word;
comment_separator = ", ";
} }
if (show_byte_offset_) { if (comment_ && inst.result_id && id_comments_.count(inst.result_id) > 0) {
SetGrey(); comments << comment_separator << id_comments_[inst.result_id].str();
auto saved_flags = stream_.flags(); comment_separator = ", ";
auto saved_fill = stream_.fill();
stream_ << " ; 0x" << std::setw(8) << std::hex << std::setfill('0')
<< inst_byte_offset;
stream_.flags(saved_flags);
stream_.fill(saved_fill);
ResetColor();
} }
stream_ << line.str();
if (!comments.str().empty()) {
// Align the comments
const uint32_t line_length = GetLineLengthWithoutColor(line.str());
uint32_t align = std::max(
{line_length + 2, last_instruction_comment_alignment_, kCommentColumn});
// Round up the alignment to a multiple of 4 for more niceness.
align = (align + 3) & ~0x3u;
last_instruction_comment_alignment_ = align;
stream_ << std::string(align - line_length, ' ') << "; " << comments.str();
} else {
last_instruction_comment_alignment_ = 0;
}
stream_ << "\n"; stream_ << "\n";
} }
void InstructionDisassembler::GenerateCommentForDecoratedId(
const spv_parsed_instruction_t& inst) {
assert(comment_);
auto opcode = static_cast<spv::Op>(inst.opcode);
std::ostringstream partial;
uint32_t id = 0;
const char* separator = "";
switch (opcode) {
case spv::Op::OpDecorate:
// Take everything after `OpDecorate %id` and associate it with id.
id = inst.words[inst.operands[0].offset];
for (uint16_t i = 1; i < inst.num_operands; i++) {
partial << separator;
separator = " ";
EmitOperand(partial, inst, i);
}
break;
default:
break;
}
if (id == 0) {
return;
}
// Add the new comment to the comments of this id
std::ostringstream& id_comment = id_comments_[id];
if (!id_comment.str().empty()) {
id_comment << ", ";
}
id_comment << partial.str();
}
void InstructionDisassembler::EmitSectionComment( void InstructionDisassembler::EmitSectionComment(
const spv_parsed_instruction_t& inst, bool& inserted_decoration_space, const spv_parsed_instruction_t& inst, bool& inserted_decoration_space,
bool& inserted_debug_space, bool& inserted_type_space) { bool& inserted_debug_space, bool& inserted_type_space) {
@ -316,36 +409,37 @@ void InstructionDisassembler::EmitSectionComment(
} }
} }
void InstructionDisassembler::EmitOperand(const spv_parsed_instruction_t& inst, void InstructionDisassembler::EmitOperand(std::ostream& stream,
const uint16_t operand_index) { const spv_parsed_instruction_t& inst,
const uint16_t operand_index) const {
assert(operand_index < inst.num_operands); assert(operand_index < inst.num_operands);
const spv_parsed_operand_t& operand = inst.operands[operand_index]; const spv_parsed_operand_t& operand = inst.operands[operand_index];
const uint32_t word = inst.words[operand.offset]; const uint32_t word = inst.words[operand.offset];
switch (operand.type) { switch (operand.type) {
case SPV_OPERAND_TYPE_RESULT_ID: case SPV_OPERAND_TYPE_RESULT_ID:
assert(false && "<result-id> is not supposed to be handled here"); assert(false && "<result-id> is not supposed to be handled here");
SetBlue(); SetBlue(stream);
stream_ << "%" << name_mapper_(word); stream << "%" << name_mapper_(word);
break; break;
case SPV_OPERAND_TYPE_ID: case SPV_OPERAND_TYPE_ID:
case SPV_OPERAND_TYPE_TYPE_ID: case SPV_OPERAND_TYPE_TYPE_ID:
case SPV_OPERAND_TYPE_SCOPE_ID: case SPV_OPERAND_TYPE_SCOPE_ID:
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
SetYellow(); SetYellow(stream);
stream_ << "%" << name_mapper_(word); stream << "%" << name_mapper_(word);
break; break;
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: { case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
spv_ext_inst_desc ext_inst; spv_ext_inst_desc ext_inst;
SetRed(); SetRed(stream);
if (grammar_.lookupExtInst(inst.ext_inst_type, word, &ext_inst) == if (grammar_.lookupExtInst(inst.ext_inst_type, word, &ext_inst) ==
SPV_SUCCESS) { SPV_SUCCESS) {
stream_ << ext_inst->name; stream << ext_inst->name;
} else { } else {
if (!spvExtInstIsNonSemantic(inst.ext_inst_type)) { if (!spvExtInstIsNonSemantic(inst.ext_inst_type)) {
assert(false && "should have caught this earlier"); assert(false && "should have caught this earlier");
} else { } else {
// for non-semantic instruction sets we can just print the number // for non-semantic instruction sets we can just print the number
stream_ << word; stream << word;
} }
} }
} break; } break;
@ -353,27 +447,27 @@ void InstructionDisassembler::EmitOperand(const spv_parsed_instruction_t& inst,
spv_opcode_desc opcode_desc; spv_opcode_desc opcode_desc;
if (grammar_.lookupOpcode(spv::Op(word), &opcode_desc)) if (grammar_.lookupOpcode(spv::Op(word), &opcode_desc))
assert(false && "should have caught this earlier"); assert(false && "should have caught this earlier");
SetRed(); SetRed(stream);
stream_ << opcode_desc->name; stream << opcode_desc->name;
} break; } break;
case SPV_OPERAND_TYPE_LITERAL_INTEGER: case SPV_OPERAND_TYPE_LITERAL_INTEGER:
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
case SPV_OPERAND_TYPE_LITERAL_FLOAT: { case SPV_OPERAND_TYPE_LITERAL_FLOAT: {
SetRed(); SetRed(stream);
EmitNumericLiteral(&stream_, inst, operand); EmitNumericLiteral(&stream, inst, operand);
ResetColor(); ResetColor(stream);
} break; } break;
case SPV_OPERAND_TYPE_LITERAL_STRING: { case SPV_OPERAND_TYPE_LITERAL_STRING: {
stream_ << "\""; stream << "\"";
SetGreen(); SetGreen(stream);
std::string str = spvDecodeLiteralStringOperand(inst, operand_index); std::string str = spvDecodeLiteralStringOperand(inst, operand_index);
for (char const& c : str) { for (char const& c : str) {
if (c == '"' || c == '\\') stream_ << '\\'; if (c == '"' || c == '\\') stream << '\\';
stream_ << c; stream << c;
} }
ResetColor(); ResetColor(stream);
stream_ << '"'; stream << '"';
} break; } break;
case SPV_OPERAND_TYPE_CAPABILITY: case SPV_OPERAND_TYPE_CAPABILITY:
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE: case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
@ -415,7 +509,7 @@ void InstructionDisassembler::EmitOperand(const spv_parsed_instruction_t& inst,
spv_operand_desc entry; spv_operand_desc entry;
if (grammar_.lookupOperand(operand.type, word, &entry)) if (grammar_.lookupOperand(operand.type, word, &entry))
assert(false && "should have caught this earlier"); assert(false && "should have caught this earlier");
stream_ << entry->name; stream << entry->name;
} break; } break;
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE: case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
case SPV_OPERAND_TYPE_FUNCTION_CONTROL: case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
@ -426,26 +520,27 @@ void InstructionDisassembler::EmitOperand(const spv_parsed_instruction_t& inst,
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
case SPV_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS: case SPV_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS:
EmitMaskOperand(operand.type, word); EmitMaskOperand(stream, operand.type, word);
break; break;
default: default:
if (spvOperandIsConcreteMask(operand.type)) { if (spvOperandIsConcreteMask(operand.type)) {
EmitMaskOperand(operand.type, word); EmitMaskOperand(stream, operand.type, word);
} else if (spvOperandIsConcrete(operand.type)) { } else if (spvOperandIsConcrete(operand.type)) {
spv_operand_desc entry; spv_operand_desc entry;
if (grammar_.lookupOperand(operand.type, word, &entry)) if (grammar_.lookupOperand(operand.type, word, &entry))
assert(false && "should have caught this earlier"); assert(false && "should have caught this earlier");
stream_ << entry->name; stream << entry->name;
} else { } else {
assert(false && "unhandled or invalid case"); assert(false && "unhandled or invalid case");
} }
break; break;
} }
ResetColor(); ResetColor(stream);
} }
void InstructionDisassembler::EmitMaskOperand(const spv_operand_type_t type, void InstructionDisassembler::EmitMaskOperand(std::ostream& stream,
const uint32_t word) { const spv_operand_type_t type,
const uint32_t word) const {
// Scan the mask from least significant bit to most significant bit. For each // Scan the mask from least significant bit to most significant bit. For each
// set bit, emit the name of that bit. Separate multiple names with '|'. // set bit, emit the name of that bit. Separate multiple names with '|'.
uint32_t remaining_word = word; uint32_t remaining_word = word;
@ -457,8 +552,8 @@ void InstructionDisassembler::EmitMaskOperand(const spv_operand_type_t type,
spv_operand_desc entry; spv_operand_desc entry;
if (grammar_.lookupOperand(type, mask, &entry)) if (grammar_.lookupOperand(type, mask, &entry))
assert(false && "should have caught this earlier"); assert(false && "should have caught this earlier");
if (num_emitted) stream_ << "|"; if (num_emitted) stream << "|";
stream_ << entry->name; stream << entry->name;
num_emitted++; num_emitted++;
} }
} }
@ -467,28 +562,35 @@ void InstructionDisassembler::EmitMaskOperand(const spv_operand_type_t type,
// of the 0 value. In many cases, that's "None". // of the 0 value. In many cases, that's "None".
spv_operand_desc entry; spv_operand_desc entry;
if (SPV_SUCCESS == grammar_.lookupOperand(type, 0, &entry)) if (SPV_SUCCESS == grammar_.lookupOperand(type, 0, &entry))
stream_ << entry->name; stream << entry->name;
} }
} }
void InstructionDisassembler::ResetColor() { void InstructionDisassembler::ResetColor(std::ostream& stream) const {
if (color_) stream_ << spvtools::clr::reset{print_}; if (color_) stream << spvtools::clr::reset{print_};
} }
void InstructionDisassembler::SetGrey() { void InstructionDisassembler::SetGrey(std::ostream& stream) const {
if (color_) stream_ << spvtools::clr::grey{print_}; if (color_) stream << spvtools::clr::grey{print_};
} }
void InstructionDisassembler::SetBlue() { void InstructionDisassembler::SetBlue(std::ostream& stream) const {
if (color_) stream_ << spvtools::clr::blue{print_}; if (color_) stream << spvtools::clr::blue{print_};
} }
void InstructionDisassembler::SetYellow() { void InstructionDisassembler::SetYellow(std::ostream& stream) const {
if (color_) stream_ << spvtools::clr::yellow{print_}; if (color_) stream << spvtools::clr::yellow{print_};
} }
void InstructionDisassembler::SetRed() { void InstructionDisassembler::SetRed(std::ostream& stream) const {
if (color_) stream_ << spvtools::clr::red{print_}; if (color_) stream << spvtools::clr::red{print_};
} }
void InstructionDisassembler::SetGreen() { void InstructionDisassembler::SetGreen(std::ostream& stream) const {
if (color_) stream_ << spvtools::clr::green{print_}; if (color_) stream << spvtools::clr::green{print_};
} }
void InstructionDisassembler::ResetColor() { ResetColor(stream_); }
void InstructionDisassembler::SetGrey() { SetGrey(stream_); }
void InstructionDisassembler::SetBlue() { SetBlue(stream_); }
void InstructionDisassembler::SetYellow() { SetYellow(stream_); }
void InstructionDisassembler::SetRed() { SetRed(stream_); }
void InstructionDisassembler::SetGreen() { SetGreen(stream_); }
} // namespace disassemble } // namespace disassemble
std::string spvInstructionBinaryToText(const spv_target_env env, std::string spvInstructionBinaryToText(const spv_target_env env,

View File

@ -16,6 +16,7 @@
#define SOURCE_DISASSEMBLE_H_ #define SOURCE_DISASSEMBLE_H_
#include <iosfwd> #include <iosfwd>
#include <sstream>
#include <string> #include <string>
#include "source/name_mapper.h" #include "source/name_mapper.h"
@ -74,13 +75,25 @@ class InstructionDisassembler {
void SetGreen(); void SetGreen();
private: private:
void ResetColor(std::ostream& stream) const;
void SetGrey(std::ostream& stream) const;
void SetBlue(std::ostream& stream) const;
void SetYellow(std::ostream& stream) const;
void SetRed(std::ostream& stream) const;
void SetGreen(std::ostream& stream) const;
// Emits an operand for the given instruction, where the instruction // Emits an operand for the given instruction, where the instruction
// is at offset words from the start of the binary. // is at offset words from the start of the binary.
void EmitOperand(const spv_parsed_instruction_t& inst, void EmitOperand(std::ostream& stream, const spv_parsed_instruction_t& inst,
const uint16_t operand_index); const uint16_t operand_index) const;
// Emits a mask expression for the given mask word of the specified type. // Emits a mask expression for the given mask word of the specified type.
void EmitMaskOperand(const spv_operand_type_t type, const uint32_t word); void EmitMaskOperand(std::ostream& stream, const spv_operand_type_t type,
const uint32_t word) const;
// Generate part of the instruction as a comment to be added to
// |id_comments_|.
void GenerateCommentForDecoratedId(const spv_parsed_instruction_t& inst);
const spvtools::AssemblyGrammar& grammar_; const spvtools::AssemblyGrammar& grammar_;
std::ostream& stream_; std::ostream& stream_;
@ -90,6 +103,13 @@ class InstructionDisassembler {
const int comment_; // Should we comment the source const int comment_; // Should we comment the source
const bool show_byte_offset_; // Should we print byte offset, in hex? const bool show_byte_offset_; // Should we print byte offset, in hex?
spvtools::NameMapper name_mapper_; spvtools::NameMapper name_mapper_;
// Some comments are generated as instructions (such as OpDecorate) are
// visited so that when the instruction with that result id is visited, the
// comment can be output.
std::unordered_map<uint32_t, std::ostringstream> id_comments_;
// Align the comments in consecutive lines for more readability.
uint32_t last_instruction_comment_alignment_;
}; };
} // namespace disassemble } // namespace disassemble

View File

@ -225,6 +225,7 @@ int32_t spvOpcodeIsSpecConstant(const spv::Op opcode) {
case spv::Op::OpSpecConstantFalse: case spv::Op::OpSpecConstantFalse:
case spv::Op::OpSpecConstant: case spv::Op::OpSpecConstant:
case spv::Op::OpSpecConstantComposite: case spv::Op::OpSpecConstantComposite:
case spv::Op::OpSpecConstantCompositeReplicateEXT:
case spv::Op::OpSpecConstantOp: case spv::Op::OpSpecConstantOp:
return true; return true;
default: default:
@ -238,6 +239,7 @@ int32_t spvOpcodeIsConstant(const spv::Op opcode) {
case spv::Op::OpConstantFalse: case spv::Op::OpConstantFalse:
case spv::Op::OpConstant: case spv::Op::OpConstant:
case spv::Op::OpConstantComposite: case spv::Op::OpConstantComposite:
case spv::Op::OpConstantCompositeReplicateEXT:
case spv::Op::OpConstantSampler: case spv::Op::OpConstantSampler:
case spv::Op::OpConstantNull: case spv::Op::OpConstantNull:
case spv::Op::OpConstantFunctionPointerINTEL: case spv::Op::OpConstantFunctionPointerINTEL:
@ -245,6 +247,7 @@ int32_t spvOpcodeIsConstant(const spv::Op opcode) {
case spv::Op::OpSpecConstantFalse: case spv::Op::OpSpecConstantFalse:
case spv::Op::OpSpecConstant: case spv::Op::OpSpecConstant:
case spv::Op::OpSpecConstantComposite: case spv::Op::OpSpecConstantComposite:
case spv::Op::OpSpecConstantCompositeReplicateEXT:
case spv::Op::OpSpecConstantOp: case spv::Op::OpSpecConstantOp:
return true; return true;
default: default:
@ -717,6 +720,16 @@ bool spvOpcodeIsImageSample(const spv::Op opcode) {
} }
} }
bool spvIsExtendedInstruction(const spv::Op opcode) {
switch (opcode) {
case spv::Op::OpExtInst:
case spv::Op::OpExtInstWithForwardRefsKHR:
return true;
default:
return false;
}
}
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode) { std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode) {
switch (opcode) { switch (opcode) {
case spv::Op::OpMemoryBarrier: case spv::Op::OpMemoryBarrier:

View File

@ -146,6 +146,9 @@ bool spvOpcodeIsLinearAlgebra(spv::Op opcode);
// Returns true for opcodes that represent image sample instructions. // Returns true for opcodes that represent image sample instructions.
bool spvOpcodeIsImageSample(spv::Op opcode); bool spvOpcodeIsImageSample(spv::Op opcode);
// Returns true if the opcode is either OpExtInst or OpExtInstWithForwardRefsKHR
bool spvIsExtendedInstruction(spv::Op opcode);
// Returns a vector containing the indices of the memory semantics <id> // Returns a vector containing the indices of the memory semantics <id>
// operands for |opcode|. // operands for |opcode|.
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode); std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode);

View File

@ -582,11 +582,13 @@ std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
} }
std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction( std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
spv_ext_inst_type_t ext_type, uint32_t key) { spv::Op opcode, spv_ext_inst_type_t ext_type, uint32_t key) {
// The Vulkan debug info extended instruction set is non-semantic so allows no // The Vulkan debug info extended instruction set is non-semantic so allows no
// forward references ever // forward references except if used through OpExtInstWithForwardRefsKHR.
if (ext_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) { if (ext_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
return [](unsigned) { return false; }; return [opcode](unsigned) {
return opcode == spv::Op::OpExtInstWithForwardRefsKHR;
};
} }
// TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward

View File

@ -140,6 +140,6 @@ std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
// of the operand can be forward declared. This function will // of the operand can be forward declared. This function will
// used in the SSA validation stage of the pipeline // used in the SSA validation stage of the pipeline
std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction( std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
spv_ext_inst_type_t ext_type, uint32_t key); spv::Op opcode, spv_ext_inst_type_t ext_type, uint32_t key);
#endif // SOURCE_OPERAND_H_ #endif // SOURCE_OPERAND_H_

View File

@ -329,12 +329,10 @@ bool ConvertToSampledImagePass::ConvertImageVariableToSampledImage(
if (sampled_image_type == nullptr) return false; if (sampled_image_type == nullptr) return false;
auto storage_class = GetStorageClass(*image_variable); auto storage_class = GetStorageClass(*image_variable);
if (storage_class == spv::StorageClass::Max) return false; if (storage_class == spv::StorageClass::Max) return false;
analysis::Pointer sampled_image_pointer(sampled_image_type, storage_class);
// Make sure |image_variable| is behind its type i.e., avoid the forward // Make sure |image_variable| is behind its type i.e., avoid the forward
// reference. // reference.
uint32_t type_id = uint32_t type_id = context()->get_type_mgr()->FindPointerToType(
context()->get_type_mgr()->GetTypeInstruction(&sampled_image_pointer); sampled_image_type_id, storage_class);
MoveInstructionNextToType(image_variable, type_id); MoveInstructionNextToType(image_variable, type_id);
return true; return true;
} }

View File

@ -92,16 +92,19 @@ void EliminateDeadOutputStoresPass::KillAllDeadStoresOfLocRef(
}); });
// Compute offset and final type of reference. If no location found // Compute offset and final type of reference. If no location found
// or any stored locations are live, return without removing stores. // or any stored locations are live, return without removing stores.
auto ptr_type = type_mgr->GetType(var->type_id())->AsPointer();
Instruction* ptr_type = get_def_use_mgr()->GetDef(var->type_id());
assert(ptr_type && "unexpected var type"); assert(ptr_type && "unexpected var type");
auto var_type = ptr_type->pointee_type(); const uint32_t kPointerTypePointeeIdx = 1;
uint32_t var_type_id =
ptr_type->GetSingleWordInOperand(kPointerTypePointeeIdx);
uint32_t ref_loc = start_loc; uint32_t ref_loc = start_loc;
auto curr_type = var_type;
if (ref->opcode() == spv::Op::OpAccessChain || if (ref->opcode() == spv::Op::OpAccessChain ||
ref->opcode() == spv::Op::OpInBoundsAccessChain) { ref->opcode() == spv::Op::OpInBoundsAccessChain) {
live_mgr->AnalyzeAccessChainLoc(ref, &curr_type, &ref_loc, &no_loc, var_type_id = live_mgr->AnalyzeAccessChainLoc(
is_patch, /* input */ false); ref, var_type_id, &ref_loc, &no_loc, is_patch, /* input */ false);
} }
const analysis::Type* curr_type = type_mgr->GetType(var_type_id);
if (no_loc || AnyLocsAreLive(ref_loc, live_mgr->GetLocSize(curr_type))) if (no_loc || AnyLocsAreLive(ref_loc, live_mgr->GetLocSize(curr_type)))
return; return;
// Kill all stores based on this reference // Kill all stores based on this reference

View File

@ -1607,27 +1607,26 @@ bool CompositeConstructFeedingExtract(
} }
// Walks the indexes chain from |start| to |end| of an OpCompositeInsert or // Walks the indexes chain from |start| to |end| of an OpCompositeInsert or
// OpCompositeExtract instruction, and returns the type of the final element // OpCompositeExtract instruction, and returns the type id of the final element
// being accessed. // being accessed. Returns 0 if a valid type could not be found.
const analysis::Type* GetElementType(uint32_t type_id, uint32_t GetElementType(uint32_t type_id, Instruction::iterator start,
Instruction::iterator start, Instruction::iterator end,
Instruction::iterator end, const analysis::DefUseManager* def_use_manager) {
const analysis::TypeManager* type_mgr) {
const analysis::Type* type = type_mgr->GetType(type_id);
for (auto index : make_range(std::move(start), std::move(end))) { for (auto index : make_range(std::move(start), std::move(end))) {
const Instruction* type_inst = def_use_manager->GetDef(type_id);
assert(index.type == SPV_OPERAND_TYPE_LITERAL_INTEGER && assert(index.type == SPV_OPERAND_TYPE_LITERAL_INTEGER &&
index.words.size() == 1); index.words.size() == 1);
if (auto* array_type = type->AsArray()) { if (type_inst->opcode() == spv::Op::OpTypeArray) {
type = array_type->element_type(); type_id = type_inst->GetSingleWordInOperand(0);
} else if (auto* matrix_type = type->AsMatrix()) { } else if (type_inst->opcode() == spv::Op::OpTypeMatrix) {
type = matrix_type->element_type(); type_id = type_inst->GetSingleWordInOperand(0);
} else if (auto* struct_type = type->AsStruct()) { } else if (type_inst->opcode() == spv::Op::OpTypeStruct) {
type = struct_type->element_types()[index.words[0]]; type_id = type_inst->GetSingleWordInOperand(index.words[0]);
} else { } else {
type = nullptr; return 0;
} }
} }
return type; return type_id;
} }
// Returns true of |inst_1| and |inst_2| have the same indexes that will be used // Returns true of |inst_1| and |inst_2| have the same indexes that will be used
@ -1712,16 +1711,11 @@ bool CompositeExtractFeedingConstruct(
// The last check it to see that the object being extracted from is the // The last check it to see that the object being extracted from is the
// correct type. // correct type.
Instruction* original_inst = def_use_mgr->GetDef(original_id); Instruction* original_inst = def_use_mgr->GetDef(original_id);
analysis::TypeManager* type_mgr = context->get_type_mgr(); uint32_t original_type_id =
const analysis::Type* original_type =
GetElementType(original_inst->type_id(), first_element_inst->begin() + 3, GetElementType(original_inst->type_id(), first_element_inst->begin() + 3,
first_element_inst->end() - 1, type_mgr); first_element_inst->end() - 1, def_use_mgr);
if (original_type == nullptr) { if (inst->type_id() != original_type_id) {
return false;
}
if (inst->type_id() != type_mgr->GetId(original_type)) {
return false; return false;
} }
@ -2011,13 +2005,15 @@ bool DoInsertedValuesCoverEntireObject(
return true; return true;
} }
// Returns the type of the element that immediately contains the element being // Returns id of the type of the element that immediately contains the element
// inserted by the OpCompositeInsert instruction |inst|. // being inserted by the OpCompositeInsert instruction |inst|. Returns 0 if it
const analysis::Type* GetContainerType(Instruction* inst) { // could not be found.
uint32_t GetContainerTypeId(Instruction* inst) {
assert(inst->opcode() == spv::Op::OpCompositeInsert); assert(inst->opcode() == spv::Op::OpCompositeInsert);
analysis::TypeManager* type_mgr = inst->context()->get_type_mgr(); analysis::DefUseManager* def_use_manager = inst->context()->get_def_use_mgr();
return GetElementType(inst->type_id(), inst->begin() + 4, inst->end() - 1, uint32_t container_type_id = GetElementType(
type_mgr); inst->type_id(), inst->begin() + 4, inst->end() - 1, def_use_manager);
return container_type_id;
} }
// Returns an OpCompositeConstruct instruction that build an object with // Returns an OpCompositeConstruct instruction that build an object with
@ -2064,18 +2060,20 @@ bool CompositeInsertToCompositeConstruct(
if (inst->NumInOperands() < 3) return false; if (inst->NumInOperands() < 3) return false;
std::map<uint32_t, uint32_t> values_inserted = GetInsertedValues(inst); std::map<uint32_t, uint32_t> values_inserted = GetInsertedValues(inst);
const analysis::Type* container_type = GetContainerType(inst); uint32_t container_type_id = GetContainerTypeId(inst);
if (container_type == nullptr) { if (container_type_id == 0) {
return false;
}
if (!DoInsertedValuesCoverEntireObject(container_type, values_inserted)) {
return false; return false;
} }
analysis::TypeManager* type_mgr = context->get_type_mgr(); analysis::TypeManager* type_mgr = context->get_type_mgr();
Instruction* construct = BuildCompositeConstruct( const analysis::Type* container_type = type_mgr->GetType(container_type_id);
type_mgr->GetId(container_type), values_inserted, inst); assert(container_type && "GetContainerTypeId returned a bad id.");
if (!DoInsertedValuesCoverEntireObject(container_type, values_inserted)) {
return false;
}
Instruction* construct =
BuildCompositeConstruct(container_type_id, values_inserted, inst);
InsertConstructedObject(inst, construct); InsertConstructedObject(inst, construct);
return true; return true;
} }

View File

@ -202,8 +202,9 @@ class IRContext {
inline IteratorRange<Module::const_inst_iterator> debugs3() const; inline IteratorRange<Module::const_inst_iterator> debugs3() const;
// Iterators for debug info instructions (excluding OpLine & OpNoLine) // Iterators for debug info instructions (excluding OpLine & OpNoLine)
// contained in this module. These are OpExtInst for DebugInfo extension // contained in this module. These are OpExtInst &
// placed between section 9 and 10. // OpExtInstWithForwardRefsKHR for DebugInfo extension placed between section
// 9 and 10.
inline Module::inst_iterator ext_inst_debuginfo_begin(); inline Module::inst_iterator ext_inst_debuginfo_begin();
inline Module::inst_iterator ext_inst_debuginfo_end(); inline Module::inst_iterator ext_inst_debuginfo_end();
inline IteratorRange<Module::inst_iterator> ext_inst_debuginfo(); inline IteratorRange<Module::inst_iterator> ext_inst_debuginfo();

View File

@ -42,7 +42,7 @@ IrLoader::IrLoader(const MessageConsumer& consumer, Module* m)
bool IsLineInst(const spv_parsed_instruction_t* inst) { bool IsLineInst(const spv_parsed_instruction_t* inst) {
const auto opcode = static_cast<spv::Op>(inst->opcode); const auto opcode = static_cast<spv::Op>(inst->opcode);
if (IsOpLineInst(opcode)) return true; if (IsOpLineInst(opcode)) return true;
if (opcode != spv::Op::OpExtInst) return false; if (!spvIsExtendedInstruction(opcode)) return false;
if (inst->ext_inst_type != SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) if (inst->ext_inst_type != SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100)
return false; return false;
const uint32_t ext_inst_index = inst->words[kExtInstSetIndex]; const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
@ -65,7 +65,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
// create a new instruction, but simply keep the information in // create a new instruction, but simply keep the information in
// struct DebugScope. // struct DebugScope.
const auto opcode = static_cast<spv::Op>(inst->opcode); const auto opcode = static_cast<spv::Op>(inst->opcode);
if (opcode == spv::Op::OpExtInst && if (spvIsExtendedInstruction(opcode) &&
spvExtInstIsDebugInfo(inst->ext_inst_type)) { spvExtInstIsDebugInfo(inst->ext_inst_type)) {
const uint32_t ext_inst_index = inst->words[kExtInstSetIndex]; const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 || if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
@ -209,10 +209,10 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
} else if (IsConstantInst(opcode) || opcode == spv::Op::OpVariable || } else if (IsConstantInst(opcode) || opcode == spv::Op::OpVariable ||
opcode == spv::Op::OpUndef) { opcode == spv::Op::OpUndef) {
module_->AddGlobalValue(std::move(spv_inst)); module_->AddGlobalValue(std::move(spv_inst));
} else if (opcode == spv::Op::OpExtInst && } else if (spvIsExtendedInstruction(opcode) &&
spvExtInstIsDebugInfo(inst->ext_inst_type)) { spvExtInstIsDebugInfo(inst->ext_inst_type)) {
module_->AddExtInstDebugInfo(std::move(spv_inst)); module_->AddExtInstDebugInfo(std::move(spv_inst));
} else if (opcode == spv::Op::OpExtInst && } else if (spvIsExtendedInstruction(opcode) &&
spvExtInstIsNonSemantic(inst->ext_inst_type)) { spvExtInstIsNonSemantic(inst->ext_inst_type)) {
// If there are no functions, add the non-semantic instructions to the // If there are no functions, add the non-semantic instructions to the
// global values. Otherwise append it to the list of the last function. // global values. Otherwise append it to the list of the last function.
@ -235,7 +235,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt); last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
if (last_dbg_scope_.GetLexicalScope() != kNoDebugScope) if (last_dbg_scope_.GetLexicalScope() != kNoDebugScope)
spv_inst->SetDebugScope(last_dbg_scope_); spv_inst->SetDebugScope(last_dbg_scope_);
if (opcode == spv::Op::OpExtInst && if (spvIsExtendedInstruction(opcode) &&
spvExtInstIsDebugInfo(inst->ext_inst_type)) { spvExtInstIsDebugInfo(inst->ext_inst_type)) {
const uint32_t ext_inst_index = inst->words[kExtInstSetIndex]; const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {

View File

@ -123,21 +123,29 @@ uint32_t LivenessManager::GetLocSize(const analysis::Type* type) const {
return 1; return 1;
} }
const analysis::Type* LivenessManager::GetComponentType( uint32_t LivenessManager::GetComponentType(uint32_t index,
uint32_t index, const analysis::Type* agg_type) const { uint32_t agg_type_id) const {
auto arr_type = agg_type->AsArray(); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
if (arr_type) return arr_type->element_type(); Instruction* agg_type_inst = def_use_mgr->GetDef(agg_type_id);
auto struct_type = agg_type->AsStruct();
if (struct_type) return struct_type->element_types()[index]; const uint32_t kArrayElementInIdx = 0;
auto mat_type = agg_type->AsMatrix(); switch (agg_type_inst->opcode()) {
if (mat_type) return mat_type->element_type(); case spv::Op::OpTypeArray:
auto vec_type = agg_type->AsVector(); case spv::Op::OpTypeMatrix:
assert(vec_type && "unexpected non-aggregate type"); case spv::Op::OpTypeVector:
return vec_type->element_type(); return agg_type_inst->GetSingleWordInOperand(kArrayElementInIdx);
case spv::Op::OpTypeStruct:
return agg_type_inst->GetSingleWordInOperand(index);
default:
assert(false && "unexpected aggregate type");
return 0;
}
} }
uint32_t LivenessManager::GetLocOffset(uint32_t index, uint32_t LivenessManager::GetLocOffset(uint32_t index,
const analysis::Type* agg_type) const { uint32_t agg_type_id) const {
analysis::TypeManager* type_mgr = context()->get_type_mgr();
const analysis::Type* agg_type = type_mgr->GetType(agg_type_id);
auto arr_type = agg_type->AsArray(); auto arr_type = agg_type->AsArray();
if (arr_type) return index * GetLocSize(arr_type->element_type()); if (arr_type) return index * GetLocSize(arr_type->element_type());
auto struct_type = agg_type->AsStruct(); auto struct_type = agg_type->AsStruct();
@ -161,12 +169,11 @@ uint32_t LivenessManager::GetLocOffset(uint32_t index,
return 0; return 0;
} }
void LivenessManager::AnalyzeAccessChainLoc(const Instruction* ac, uint32_t LivenessManager::AnalyzeAccessChainLoc(const Instruction* ac,
const analysis::Type** curr_type, uint32_t curr_type_id,
uint32_t* offset, bool* no_loc, uint32_t* offset, bool* no_loc,
bool is_patch, bool input) { bool is_patch, bool input) {
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
analysis::TypeManager* type_mgr = context()->get_type_mgr();
analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr(); analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
// For tesc, tese and geom input variables, and tesc output variables, // For tesc, tese and geom input variables, and tesc output variables,
// first array index does not contribute to offset. // first array index does not contribute to offset.
@ -178,15 +185,18 @@ void LivenessManager::AnalyzeAccessChainLoc(const Instruction* ac,
(!input && stage == spv::ExecutionModel::TessellationControl)) (!input && stage == spv::ExecutionModel::TessellationControl))
skip_first_index = !is_patch; skip_first_index = !is_patch;
uint32_t ocnt = 0; uint32_t ocnt = 0;
ac->WhileEachInOperand([this, &ocnt, def_use_mgr, type_mgr, deco_mgr, ac->WhileEachInOperand([this, &ocnt, def_use_mgr, deco_mgr, &curr_type_id,
curr_type, offset, no_loc, offset, no_loc,
skip_first_index](const uint32_t* opnd) { skip_first_index](const uint32_t* opnd) {
if (ocnt >= 1) { if (ocnt >= 1) {
// Skip first index's contribution to offset if indicated // Skip first index's contribution to offset if indicated
Instruction* curr_type_inst = def_use_mgr->GetDef(curr_type_id);
if (ocnt == 1 && skip_first_index) { if (ocnt == 1 && skip_first_index) {
auto arr_type = (*curr_type)->AsArray(); assert(curr_type_inst->opcode() == spv::Op::OpTypeArray &&
assert(arr_type && "unexpected wrapper type"); "unexpected wrapper type");
*curr_type = arr_type->element_type(); const uint32_t kArrayElementTypeInIdx = 0;
curr_type_id =
curr_type_inst->GetSingleWordInOperand(kArrayElementTypeInIdx);
ocnt++; ocnt++;
return true; return true;
} }
@ -196,12 +206,10 @@ void LivenessManager::AnalyzeAccessChainLoc(const Instruction* ac,
// If current type is struct, look for location decoration on member and // If current type is struct, look for location decoration on member and
// reset offset if found. // reset offset if found.
auto index = idx_inst->GetSingleWordInOperand(0); auto index = idx_inst->GetSingleWordInOperand(0);
auto str_type = (*curr_type)->AsStruct(); if (curr_type_inst->opcode() == spv::Op::OpTypeStruct) {
if (str_type) {
uint32_t loc = 0; uint32_t loc = 0;
auto str_type_id = type_mgr->GetId(str_type);
bool no_mem_loc = deco_mgr->WhileEachDecoration( bool no_mem_loc = deco_mgr->WhileEachDecoration(
str_type_id, uint32_t(spv::Decoration::Location), curr_type_id, uint32_t(spv::Decoration::Location),
[&loc, index, no_loc](const Instruction& deco) { [&loc, index, no_loc](const Instruction& deco) {
assert(deco.opcode() == spv::Op::OpMemberDecorate && assert(deco.opcode() == spv::Op::OpMemberDecorate &&
"unexpected decoration"); "unexpected decoration");
@ -216,19 +224,20 @@ void LivenessManager::AnalyzeAccessChainLoc(const Instruction* ac,
}); });
if (!no_mem_loc) { if (!no_mem_loc) {
*offset = loc; *offset = loc;
*curr_type = GetComponentType(index, *curr_type); curr_type_id = curr_type_inst->GetSingleWordInOperand(index);
ocnt++; ocnt++;
return true; return true;
} }
} }
// Update offset and current type based on constant index. // Update offset and current type based on constant index.
*offset += GetLocOffset(index, *curr_type); *offset += GetLocOffset(index, curr_type_id);
*curr_type = GetComponentType(index, *curr_type); curr_type_id = GetComponentType(index, curr_type_id);
} }
ocnt++; ocnt++;
return true; return true;
}); });
return curr_type_id;
} }
void LivenessManager::MarkRefLive(const Instruction* ref, Instruction* var) { void LivenessManager::MarkRefLive(const Instruction* ref, Instruction* var) {
@ -268,8 +277,15 @@ void LivenessManager::MarkRefLive(const Instruction* ref, Instruction* var) {
// through constant indices and mark those locs live. Assert if no location // through constant indices and mark those locs live. Assert if no location
// found. // found.
uint32_t offset = loc; uint32_t offset = loc;
auto curr_type = var_type; Instruction* ptr_type_inst =
AnalyzeAccessChainLoc(ref, &curr_type, &offset, &no_loc, is_patch); context()->get_def_use_mgr()->GetDef(var->type_id());
assert(ptr_type && "unexpected var type");
const uint32_t kPointerTypePointeeIdx = 1;
uint32_t var_type_id =
ptr_type_inst->GetSingleWordInOperand(kPointerTypePointeeIdx);
uint32_t curr_type_id =
AnalyzeAccessChainLoc(ref, var_type_id, &offset, &no_loc, is_patch);
auto curr_type = type_mgr->GetType(curr_type_id);
assert(!no_loc && "missing input variable location"); assert(!no_loc && "missing input variable location");
MarkLocsLive(offset, GetLocSize(curr_type)); MarkLocsLive(offset, GetLocSize(curr_type));
} }
@ -277,15 +293,18 @@ void LivenessManager::MarkRefLive(const Instruction* ref, Instruction* var) {
void LivenessManager::ComputeLiveness() { void LivenessManager::ComputeLiveness() {
InitializeAnalysis(); InitializeAnalysis();
analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
analysis::TypeManager* type_mgr = context()->get_type_mgr();
// Process all input variables // Process all input variables
for (auto& var : context()->types_values()) { for (auto& var : context()->types_values()) {
if (var.opcode() != spv::Op::OpVariable) { if (var.opcode() != spv::Op::OpVariable) {
continue; continue;
} }
analysis::Type* var_type = type_mgr->GetType(var.type_id()); Instruction* var_type_inst = def_use_mgr->GetDef(var.type_id());
analysis::Pointer* ptr_type = var_type->AsPointer(); assert(var_type_inst->opcode() == spv::Op::OpTypePointer &&
if (ptr_type->storage_class() != spv::StorageClass::Input) { "Expected a pointer type");
const uint32_t kPointerTypeStorageClassInIdx = 0;
spv::StorageClass sc = static_cast<spv::StorageClass>(
var_type_inst->GetSingleWordInOperand(kPointerTypeStorageClassInIdx));
if (sc != spv::StorageClass::Input) {
continue; continue;
} }
// If var is builtin, mark live if analyzed and continue to next variable // If var is builtin, mark live if analyzed and continue to next variable
@ -295,14 +314,15 @@ void LivenessManager::ComputeLiveness() {
// continue to next variable. Input interface blocks will only appear // continue to next variable. Input interface blocks will only appear
// in tesc, tese and geom shaders. Will need to strip off one level of // in tesc, tese and geom shaders. Will need to strip off one level of
// arrayness to get to block type. // arrayness to get to block type.
auto pte_type = ptr_type->pointee_type(); const uint32_t kPointerTypePointeeTypeInIdx = 1;
auto arr_type = pte_type->AsArray(); uint32_t pte_type_id =
if (arr_type) { var_type_inst->GetSingleWordInOperand(kPointerTypePointeeTypeInIdx);
auto elt_type = arr_type->element_type(); Instruction* pte_type_inst = def_use_mgr->GetDef(pte_type_id);
auto str_type = elt_type->AsStruct(); if (pte_type_inst->opcode() == spv::Op::OpTypeArray) {
if (str_type) { uint32_t array_elt_type_id = pte_type_inst->GetSingleWordInOperand(0);
auto str_type_id = type_mgr->GetId(str_type); Instruction* arr_elt_type = def_use_mgr->GetDef(array_elt_type_id);
if (AnalyzeBuiltIn(str_type_id)) continue; if (arr_elt_type->opcode() == spv::Op::OpTypeStruct) {
if (AnalyzeBuiltIn(array_elt_type_id)) continue;
} }
} }
// Mark all used locations of var live // Mark all used locations of var live

View File

@ -41,13 +41,13 @@ class LivenessManager {
// Return true if builtin |bi| is being analyzed. // Return true if builtin |bi| is being analyzed.
bool IsAnalyzedBuiltin(uint32_t bi); bool IsAnalyzedBuiltin(uint32_t bi);
// Determine starting loc |offset| and the type |cur_type| of // Return the result type of |ac| when applied to |cur_type_id|. Set
// access chain |ac|. Set |no_loc| to true if no loc found. // |no_loc| to true if no loc found. Set |is_patch| indicates if the variable
// |is_patch| indicates if patch variable. |input| is true // is a patch variable. Set |input| if the variable is an input variable.
// if input variable, otherwise output variable. // Otherwise it is assumed that the variable is an output variable.
void AnalyzeAccessChainLoc(const Instruction* ac, uint32_t AnalyzeAccessChainLoc(const Instruction* ac, uint32_t curr_type_id,
const analysis::Type** curr_type, uint32_t* offset, uint32_t* offset, bool* no_loc, bool is_patch,
bool* no_loc, bool is_patch, bool input = true); bool input = true);
// Return size of |type_id| in units of locations // Return size of |type_id| in units of locations
uint32_t GetLocSize(const analysis::Type* type) const; uint32_t GetLocSize(const analysis::Type* type) const;
@ -68,13 +68,12 @@ class LivenessManager {
// Mark |count| locations starting at location |start|. // Mark |count| locations starting at location |start|.
void MarkLocsLive(uint32_t start, uint32_t count); void MarkLocsLive(uint32_t start, uint32_t count);
// Return type of component of aggregate type |agg_type| at |index| // Return type of the member |index| in the aggregate type |agg_type_id|.
const analysis::Type* GetComponentType(uint32_t index, uint32_t GetComponentType(uint32_t index, uint32_t agg_type_id) const;
const analysis::Type* agg_type) const;
// Return offset of |index| into aggregate type |agg_type| in units of // Return offset of member |index| in the aggregate type |agg_type_id| in
// input locations // units of input locations.
uint32_t GetLocOffset(uint32_t index, const analysis::Type* agg_type) const; uint32_t GetLocOffset(uint32_t index, uint32_t agg_type_id) const;
// Populate live_locs_ and live_builtins_ // Populate live_locs_ and live_builtins_
void ComputeLiveness(); void ComputeLiveness();

View File

@ -0,0 +1,112 @@
// Copyright (c) 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "source/opt/opextinst_forward_ref_fixup_pass.h"
#include <string>
#include <unordered_set>
#include "source/extensions.h"
#include "source/opt/ir_context.h"
#include "source/opt/module.h"
#include "type_manager.h"
namespace spvtools {
namespace opt {
namespace {
// Returns true if the instruction |inst| has a forward reference to another
// debug instruction.
// |debug_ids| contains the list of IDs belonging to debug instructions.
// |seen_ids| contains the list of IDs already seen.
bool HasForwardReference(const Instruction& inst,
const std::unordered_set<uint32_t>& debug_ids,
const std::unordered_set<uint32_t>& seen_ids) {
const uint32_t num_in_operands = inst.NumInOperands();
for (uint32_t i = 0; i < num_in_operands; ++i) {
const Operand& op = inst.GetInOperand(i);
if (!spvIsIdType(op.type)) continue;
if (debug_ids.count(op.AsId()) == 0) continue;
if (seen_ids.count(op.AsId()) == 0) return true;
}
return false;
}
// Replace |inst| opcode with OpExtInstWithForwardRefsKHR or OpExtInst
// if required to comply with forward references.
bool ReplaceOpcodeIfRequired(Instruction& inst, bool hasForwardReferences) {
if (hasForwardReferences &&
inst.opcode() != spv::Op::OpExtInstWithForwardRefsKHR)
inst.SetOpcode(spv::Op::OpExtInstWithForwardRefsKHR);
else if (!hasForwardReferences && inst.opcode() != spv::Op::OpExtInst)
inst.SetOpcode(spv::Op::OpExtInst);
else
return false;
return true;
}
// Returns all the result IDs of the instructions in |range|.
std::unordered_set<uint32_t> gatherResultIds(
const IteratorRange<Module::inst_iterator>& range) {
std::unordered_set<uint32_t> output;
for (const auto& it : range) output.insert(it.result_id());
return output;
}
} // namespace
Pass::Status OpExtInstWithForwardReferenceFixupPass::Process() {
std::unordered_set<uint32_t> seen_ids =
gatherResultIds(get_module()->ext_inst_imports());
std::unordered_set<uint32_t> debug_ids =
gatherResultIds(get_module()->ext_inst_debuginfo());
for (uint32_t id : seen_ids) debug_ids.insert(id);
bool moduleChanged = false;
bool hasAtLeastOneForwardReference = false;
IRContext* ctx = context();
for (Instruction& inst : get_module()->ext_inst_debuginfo()) {
if (inst.opcode() != spv::Op::OpExtInst &&
inst.opcode() != spv::Op::OpExtInstWithForwardRefsKHR)
continue;
seen_ids.insert(inst.result_id());
bool hasForwardReferences = HasForwardReference(inst, debug_ids, seen_ids);
hasAtLeastOneForwardReference |= hasForwardReferences;
if (ReplaceOpcodeIfRequired(inst, hasForwardReferences)) {
moduleChanged = true;
ctx->AnalyzeUses(&inst);
}
}
if (hasAtLeastOneForwardReference !=
ctx->get_feature_mgr()->HasExtension(
kSPV_KHR_relaxed_extended_instruction)) {
if (hasAtLeastOneForwardReference)
ctx->AddExtension("SPV_KHR_relaxed_extended_instruction");
else
ctx->RemoveExtension(Extension::kSPV_KHR_relaxed_extended_instruction);
moduleChanged = true;
}
return moduleChanged ? Status::SuccessWithChange
: Status::SuccessWithoutChange;
}
} // namespace opt
} // namespace spvtools

View File

@ -0,0 +1,48 @@
// Copyright (c) 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SOURCE_OPT_OPEXTINST_FORWARD_REF_FIXUP_H
#define SOURCE_OPT_OPEXTINST_FORWARD_REF_FIXUP_H
#include "source/opt/ir_context.h"
#include "source/opt/module.h"
#include "source/opt/pass.h"
namespace spvtools {
namespace opt {
class OpExtInstWithForwardReferenceFixupPass : public Pass {
public:
const char* name() const override { return "fix-opextinst-opcodes"; }
Status Process() override;
IRContext::Analysis GetPreservedAnalyses() override {
return IRContext::kAnalysisInstrToBlockMapping |
IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap |
IRContext::kAnalysisScalarEvolution |
IRContext::kAnalysisRegisterPressure |
IRContext::kAnalysisValueNumberTable |
IRContext::kAnalysisStructuredCFG |
IRContext::kAnalysisBuiltinVarId |
IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisTypes |
IRContext::kAnalysisDefUse | IRContext::kAnalysisConstants;
}
};
} // namespace opt
} // namespace spvtools
#endif // SOURCE_OPT_OPEXTINST_FORWARD_REF_FIXUP_H

View File

@ -169,7 +169,8 @@ Optimizer& Optimizer::RegisterLegalizationPasses(bool preserve_interface) {
.RegisterPass(CreateAggressiveDCEPass(preserve_interface)) .RegisterPass(CreateAggressiveDCEPass(preserve_interface))
.RegisterPass(CreateRemoveUnusedInterfaceVariablesPass()) .RegisterPass(CreateRemoveUnusedInterfaceVariablesPass())
.RegisterPass(CreateInterpolateFixupPass()) .RegisterPass(CreateInterpolateFixupPass())
.RegisterPass(CreateInvocationInterlockPlacementPass()); .RegisterPass(CreateInvocationInterlockPlacementPass())
.RegisterPass(CreateOpExtInstWithForwardReferenceFixupPass());
} }
Optimizer& Optimizer::RegisterLegalizationPasses() { Optimizer& Optimizer::RegisterLegalizationPasses() {
@ -323,6 +324,8 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag,
RegisterPass(CreateStripReflectInfoPass()); RegisterPass(CreateStripReflectInfoPass());
} else if (pass_name == "strip-nonsemantic") { } else if (pass_name == "strip-nonsemantic") {
RegisterPass(CreateStripNonSemanticInfoPass()); RegisterPass(CreateStripNonSemanticInfoPass());
} else if (pass_name == "fix-opextinst-opcodes") {
RegisterPass(CreateOpExtInstWithForwardReferenceFixupPass());
} else if (pass_name == "set-spec-const-default-value") { } else if (pass_name == "set-spec-const-default-value") {
if (pass_args.size() > 0) { if (pass_args.size() > 0) {
auto spec_ids_vals = auto spec_ids_vals =
@ -1146,6 +1149,12 @@ Optimizer::PassToken CreateModifyMaximalReconvergencePass(bool add) {
return MakeUnique<Optimizer::PassToken::Impl>( return MakeUnique<Optimizer::PassToken::Impl>(
MakeUnique<opt::ModifyMaximalReconvergence>(add)); MakeUnique<opt::ModifyMaximalReconvergence>(add));
} }
Optimizer::PassToken CreateOpExtInstWithForwardReferenceFixupPass() {
return MakeUnique<Optimizer::PassToken::Impl>(
MakeUnique<opt::OpExtInstWithForwardReferenceFixupPass>());
}
} // namespace spvtools } // namespace spvtools
extern "C" { extern "C" {

View File

@ -65,6 +65,7 @@
#include "source/opt/merge_return_pass.h" #include "source/opt/merge_return_pass.h"
#include "source/opt/modify_maximal_reconvergence.h" #include "source/opt/modify_maximal_reconvergence.h"
#include "source/opt/null_pass.h" #include "source/opt/null_pass.h"
#include "source/opt/opextinst_forward_ref_fixup_pass.h"
#include "source/opt/private_to_local_pass.h" #include "source/opt/private_to_local_pass.h"
#include "source/opt/reduce_load_size.h" #include "source/opt/reduce_load_size.h"
#include "source/opt/redundancy_elimination.h" #include "source/opt/redundancy_elimination.h"

View File

@ -43,7 +43,7 @@ Pass::Status StripDebugInfoPass::Process() {
// see if this string is used anywhere by a non-semantic instruction // see if this string is used anywhere by a non-semantic instruction
bool no_nonsemantic_use = bool no_nonsemantic_use =
def_use->WhileEachUser(&inst, [def_use](Instruction* use) { def_use->WhileEachUser(&inst, [def_use](Instruction* use) {
if (use->opcode() == spv::Op::OpExtInst) { if (spvIsExtendedInstruction(use->opcode())) {
auto ext_inst_set = auto ext_inst_set =
def_use->GetDef(use->GetSingleWordInOperand(0u)); def_use->GetDef(use->GetSingleWordInOperand(0u));
const std::string extension_name = const std::string extension_name =

View File

@ -96,7 +96,7 @@ Pass::Status StripNonSemanticInfoPass::Process() {
if (!non_semantic_sets.empty()) { if (!non_semantic_sets.empty()) {
context()->module()->ForEachInst( context()->module()->ForEachInst(
[&non_semantic_sets, &to_remove](Instruction* inst) { [&non_semantic_sets, &to_remove](Instruction* inst) {
if (inst->opcode() == spv::Op::OpExtInst) { if (spvIsExtendedInstruction(inst->opcode())) {
if (non_semantic_sets.find(inst->GetSingleWordInOperand(0)) != if (non_semantic_sets.find(inst->GetSingleWordInOperand(0)) !=
non_semantic_sets.end()) { non_semantic_sets.end()) {
to_remove.push_back(inst); to_remove.push_back(inst);

View File

@ -399,6 +399,33 @@ ExtensionSet getExtensionsRelatedTo(const CapabilitySet& capabilities,
return output; return output;
} }
bool hasOpcodeConflictingCapabilities(spv::Op opcode) {
switch (opcode) {
case spv::Op::OpBeginInvocationInterlockEXT:
case spv::Op::OpEndInvocationInterlockEXT:
case spv::Op::OpGroupNonUniformIAdd:
case spv::Op::OpGroupNonUniformFAdd:
case spv::Op::OpGroupNonUniformIMul:
case spv::Op::OpGroupNonUniformFMul:
case spv::Op::OpGroupNonUniformSMin:
case spv::Op::OpGroupNonUniformUMin:
case spv::Op::OpGroupNonUniformFMin:
case spv::Op::OpGroupNonUniformSMax:
case spv::Op::OpGroupNonUniformUMax:
case spv::Op::OpGroupNonUniformFMax:
case spv::Op::OpGroupNonUniformBitwiseAnd:
case spv::Op::OpGroupNonUniformBitwiseOr:
case spv::Op::OpGroupNonUniformBitwiseXor:
case spv::Op::OpGroupNonUniformLogicalAnd:
case spv::Op::OpGroupNonUniformLogicalOr:
case spv::Op::OpGroupNonUniformLogicalXor:
return true;
default:
return false;
}
}
} // namespace } // namespace
TrimCapabilitiesPass::TrimCapabilitiesPass() TrimCapabilitiesPass::TrimCapabilitiesPass()
@ -416,10 +443,7 @@ TrimCapabilitiesPass::TrimCapabilitiesPass()
void TrimCapabilitiesPass::addInstructionRequirementsForOpcode( void TrimCapabilitiesPass::addInstructionRequirementsForOpcode(
spv::Op opcode, CapabilitySet* capabilities, spv::Op opcode, CapabilitySet* capabilities,
ExtensionSet* extensions) const { ExtensionSet* extensions) const {
// Ignoring OpBeginInvocationInterlockEXT and OpEndInvocationInterlockEXT if (hasOpcodeConflictingCapabilities(opcode)) {
// because they have three possible capabilities, only one of which is needed
if (opcode == spv::Op::OpBeginInvocationInterlockEXT ||
opcode == spv::Op::OpEndInvocationInterlockEXT) {
return; return;
} }

View File

@ -81,6 +81,11 @@ class TrimCapabilitiesPass : public Pass {
spv::Capability::FragmentShaderPixelInterlockEXT, spv::Capability::FragmentShaderPixelInterlockEXT,
spv::Capability::FragmentShaderSampleInterlockEXT, spv::Capability::FragmentShaderSampleInterlockEXT,
spv::Capability::FragmentShaderShadingRateInterlockEXT, spv::Capability::FragmentShaderShadingRateInterlockEXT,
spv::Capability::GroupNonUniform,
spv::Capability::GroupNonUniformArithmetic,
spv::Capability::GroupNonUniformClustered,
spv::Capability::GroupNonUniformPartitionedNV,
spv::Capability::GroupNonUniformVote,
spv::Capability::Groups, spv::Capability::Groups,
spv::Capability::ImageMSArray, spv::Capability::ImageMSArray,
spv::Capability::Int16, spv::Capability::Int16,
@ -99,7 +104,6 @@ class TrimCapabilitiesPass : public Pass {
spv::Capability::StorageUniform16, spv::Capability::StorageUniform16,
spv::Capability::StorageUniformBufferBlock16, spv::Capability::StorageUniformBufferBlock16,
spv::Capability::VulkanMemoryModelDeviceScope, spv::Capability::VulkanMemoryModelDeviceScope,
spv::Capability::GroupNonUniformPartitionedNV
// clang-format on // clang-format on
}; };

View File

@ -454,12 +454,7 @@ uint32_t TypeManager::FindPointerToType(uint32_t type_id,
spv::StorageClass storage_class) { spv::StorageClass storage_class) {
Type* pointeeTy = GetType(type_id); Type* pointeeTy = GetType(type_id);
Pointer pointerTy(pointeeTy, storage_class); Pointer pointerTy(pointeeTy, storage_class);
if (pointeeTy->IsUniqueType()) {
// Non-ambiguous type. Get the pointer type through the type manager.
return GetTypeInstruction(&pointerTy);
}
// Ambiguous type, do a linear search.
Module::inst_iterator type_itr = context()->module()->types_values_begin(); Module::inst_iterator type_itr = context()->module()->types_values_begin();
for (; type_itr != context()->module()->types_values_end(); ++type_itr) { for (; type_itr != context()->module()->types_values_end(); ++type_itr) {
const Instruction* type_inst = &*type_itr; const Instruction* type_inst = &*type_itr;
@ -472,8 +467,10 @@ uint32_t TypeManager::FindPointerToType(uint32_t type_id,
} }
// Must create the pointer type. // Must create the pointer type.
// TODO(1841): Handle id overflow.
uint32_t resultId = context()->TakeNextId(); uint32_t resultId = context()->TakeNextId();
if (resultId == 0) {
return 0;
}
std::unique_ptr<Instruction> type_inst( std::unique_ptr<Instruction> type_inst(
new Instruction(context(), spv::Op::OpTypePointer, 0, resultId, new Instruction(context(), spv::Op::OpTypePointer, 0, resultId,
{{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS, {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,

View File

@ -227,8 +227,7 @@ spv_result_t spvTextEncodeOperand(const spvtools::AssemblyGrammar& grammar,
// Set the extended instruction type. // Set the extended instruction type.
// The import set id is the 3rd operand of OpExtInst. // The import set id is the 3rd operand of OpExtInst.
if (spv::Op(pInst->opcode) == spv::Op::OpExtInst && if (spvIsExtendedInstruction(pInst->opcode) && pInst->words.size() == 4) {
pInst->words.size() == 4) {
auto ext_inst_type = context->getExtInstTypeForId(pInst->words[3]); auto ext_inst_type = context->getExtInstTypeForId(pInst->words[3]);
if (ext_inst_type == SPV_EXT_INST_TYPE_NONE) { if (ext_inst_type == SPV_EXT_INST_TYPE_NONE) {
return context->diagnostic() return context->diagnostic()

View File

@ -15,6 +15,7 @@
#ifndef SOURCE_VAL_DECORATION_H_ #ifndef SOURCE_VAL_DECORATION_H_
#define SOURCE_VAL_DECORATION_H_ #define SOURCE_VAL_DECORATION_H_
#include <cassert>
#include <cstdint> #include <cstdint>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -55,6 +56,12 @@ namespace val {
// params_ = vector { 2 } // params_ = vector { 2 }
// struct_member_index_ = 2 // struct_member_index_ = 2
// //
// Example 4: Decoration for a Builtin:
// OpDecorate %var BuiltIn FragDepth
// dec_type_ = spv::Decoration::BuiltIn
// params_ = vector { FragDepth }
// struct_member_index_ = kInvalidMember
//
class Decoration { class Decoration {
public: public:
enum { kInvalidMember = -1 }; enum { kInvalidMember = -1 };
@ -68,6 +75,10 @@ class Decoration {
spv::Decoration dec_type() const { return dec_type_; } spv::Decoration dec_type() const { return dec_type_; }
std::vector<uint32_t>& params() { return params_; } std::vector<uint32_t>& params() { return params_; }
const std::vector<uint32_t>& params() const { return params_; } const std::vector<uint32_t>& params() const { return params_; }
spv::BuiltIn builtin() const {
assert(dec_type_ == spv::Decoration::BuiltIn);
return spv::BuiltIn(params_[0]);
}
inline bool operator<(const Decoration& rhs) const { inline bool operator<(const Decoration& rhs) const {
// Note: Sort by struct_member_index_ first, then type, so look up can be // Note: Sort by struct_member_index_ first, then type, so look up can be

View File

@ -22,6 +22,7 @@
#include <vector> #include <vector>
#include "source/ext_inst.h" #include "source/ext_inst.h"
#include "source/opcode.h"
#include "source/table.h" #include "source/table.h"
#include "spirv-tools/libspirv.h" #include "spirv-tools/libspirv.h"
@ -87,13 +88,13 @@ class Instruction {
} }
bool IsNonSemantic() const { bool IsNonSemantic() const {
return opcode() == spv::Op::OpExtInst && return spvIsExtendedInstruction(opcode()) &&
spvExtInstIsNonSemantic(inst_.ext_inst_type); spvExtInstIsNonSemantic(inst_.ext_inst_type);
} }
/// True if this is an OpExtInst for debug info extension. /// True if this is an OpExtInst for debug info extension.
bool IsDebugInfo() const { bool IsDebugInfo() const {
return opcode() == spv::Op::OpExtInst && return spvIsExtendedInstruction(opcode()) &&
spvExtInstIsDebugInfo(inst_.ext_inst_type); spvExtInstIsDebugInfo(inst_.ext_inst_type);
} }

View File

@ -52,6 +52,7 @@ spv_result_t ValidateAdjacency(ValidationState_t& _) {
adjacency_status == IN_NEW_FUNCTION ? IN_ENTRY_BLOCK : PHI_VALID; adjacency_status == IN_NEW_FUNCTION ? IN_ENTRY_BLOCK : PHI_VALID;
break; break;
case spv::Op::OpExtInst: case spv::Op::OpExtInst:
case spv::Op::OpExtInstWithForwardRefsKHR:
// If it is a debug info instruction, we do not change the status to // If it is a debug info instruction, we do not change the status to
// allow debug info instructions before OpVariable in a function. // allow debug info instructions before OpVariable in a function.
// TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We need // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We need

View File

@ -741,7 +741,7 @@ std::string BuiltInsValidator::GetReferenceDesc(
ss << " which is decorated with BuiltIn "; ss << " which is decorated with BuiltIn ";
ss << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, ss << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]); (uint32_t)decoration.builtin());
if (function_id_) { if (function_id_) {
ss << " in function <" << function_id_ << ">"; ss << " in function <" << function_id_ << ">";
if (execution_model != spv::ExecutionModel::Max) { if (execution_model != spv::ExecutionModel::Max) {
@ -1170,7 +1170,7 @@ spv_result_t BuiltInsValidator::ValidateNotCalledWithExecutionModel(
const char* execution_model_str = _.grammar().lookupOperandName( const char* execution_model_str = _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_EXECUTION_MODEL, uint32_t(execution_model)); SPV_OPERAND_TYPE_EXECUTION_MODEL, uint32_t(execution_model));
const char* built_in_str = _.grammar().lookupOperandName( const char* built_in_str = _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]); SPV_OPERAND_TYPE_BUILT_IN, (uint32_t)decoration.builtin());
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< (vuid < 0 ? std::string("") : _.VkErrorID(vuid)) << comment << (vuid < 0 ? std::string("") : _.VkErrorID(vuid)) << comment
<< " " << GetIdDesc(referenced_inst) << " depends on " << " " << GetIdDesc(referenced_inst) << " depends on "
@ -1201,13 +1201,14 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
const Decoration& decoration, const Instruction& built_in_inst, const Decoration& decoration, const Instruction& built_in_inst,
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
uint32_t operand = decoration.params()[0]; uint32_t operand = (uint32_t)decoration.builtin();
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input && storage_class != spv::StorageClass::Input &&
storage_class != spv::StorageClass::Output) { storage_class != spv::StorageClass::Output) {
uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4190 : 4199; uint32_t vuid =
(decoration.builtin() == spv::BuiltIn::ClipDistance) ? 4190 : 4199;
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn " << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@ -1221,7 +1222,8 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
if (storage_class == spv::StorageClass::Input) { if (storage_class == spv::StorageClass::Input) {
assert(function_id_ == 0); assert(function_id_ == 0);
uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4188 : 4197; uint32_t vuid =
(decoration.builtin() == spv::BuiltIn::ClipDistance) ? 4188 : 4197;
id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
&BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
"Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be " "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
@ -1247,7 +1249,8 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
if (storage_class == spv::StorageClass::Output) { if (storage_class == spv::StorageClass::Output) {
assert(function_id_ == 0); assert(function_id_ == 0);
uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4189 : 4198; uint32_t vuid =
(decoration.builtin() == spv::BuiltIn::ClipDistance) ? 4189 : 4198;
id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
&BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
"Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be " "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
@ -1266,7 +1269,7 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
[this, &decoration, &referenced_from_inst]( [this, &decoration, &referenced_from_inst](
const std::string& message) -> spv_result_t { const std::string& message) -> spv_result_t {
uint32_t vuid = uint32_t vuid =
(spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) (decoration.builtin() == spv::BuiltIn::ClipDistance)
? 4191 ? 4191
: 4200; : 4200;
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@ -1274,7 +1277,7 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit float array. " << " variable needs to be a 32-bit float array. "
<< message; << message;
})) { })) {
@ -1294,7 +1297,7 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
[this, &decoration, &referenced_from_inst]( [this, &decoration, &referenced_from_inst](
const std::string& message) -> spv_result_t { const std::string& message) -> spv_result_t {
uint32_t vuid = uint32_t vuid =
(spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) (decoration.builtin() == spv::BuiltIn::ClipDistance)
? 4191 ? 4191
: 4200; : 4200;
return _.diag(SPV_ERROR_INVALID_DATA, return _.diag(SPV_ERROR_INVALID_DATA,
@ -1303,7 +1306,7 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit float array. " << " variable needs to be a 32-bit float array. "
<< message; << message;
})) { })) {
@ -1315,7 +1318,7 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
[this, &decoration, &referenced_from_inst]( [this, &decoration, &referenced_from_inst](
const std::string& message) -> spv_result_t { const std::string& message) -> spv_result_t {
uint32_t vuid = uint32_t vuid =
(spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) (decoration.builtin() == spv::BuiltIn::ClipDistance)
? 4191 ? 4191
: 4200; : 4200;
return _.diag(SPV_ERROR_INVALID_DATA, return _.diag(SPV_ERROR_INVALID_DATA,
@ -1324,7 +1327,7 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit float array. " << " variable needs to be a 32-bit float array. "
<< message; << message;
})) { })) {
@ -1335,8 +1338,9 @@ spv_result_t BuiltInsValidator::ValidateClipOrCullDistanceAtReference(
} }
default: { default: {
uint32_t vuid = uint32_t vuid = (decoration.builtin() == spv::BuiltIn::ClipDistance)
(spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4187 : 4196; ? 4187
: 4196;
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn " << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@ -2542,7 +2546,7 @@ spv_result_t BuiltInsValidator::ValidateTessLevelAtReference(
const Decoration& decoration, const Instruction& built_in_inst, const Decoration& decoration, const Instruction& built_in_inst,
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
uint32_t operand = decoration.params()[0]; uint32_t operand = (uint32_t)decoration.builtin();
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
@ -2561,7 +2565,8 @@ spv_result_t BuiltInsValidator::ValidateTessLevelAtReference(
if (storage_class == spv::StorageClass::Input) { if (storage_class == spv::StorageClass::Input) {
assert(function_id_ == 0); assert(function_id_ == 0);
uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::TessLevelOuter) ? 4391 : 4395; uint32_t vuid =
(decoration.builtin() == spv::BuiltIn::TessLevelOuter) ? 4391 : 4395;
id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
&BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
"Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be " "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@ -2574,7 +2579,8 @@ spv_result_t BuiltInsValidator::ValidateTessLevelAtReference(
if (storage_class == spv::StorageClass::Output) { if (storage_class == spv::StorageClass::Output) {
assert(function_id_ == 0); assert(function_id_ == 0);
uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::TessLevelOuter) ? 4392 : 4396; uint32_t vuid =
(decoration.builtin() == spv::BuiltIn::TessLevelOuter) ? 4392 : 4396;
id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
&BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid, &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
"Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be " "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
@ -2724,12 +2730,13 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtDefinition(
[this, &decoration, [this, &decoration,
&inst](const std::string& message) -> spv_result_t { &inst](const std::string& message) -> spv_result_t {
uint32_t vuid = uint32_t vuid =
(spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::Layer) ? 4276 : 4408; (decoration.builtin() == spv::BuiltIn::Layer) ? 4276 : 4408;
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(vuid) << _.VkErrorID(vuid)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< "variable needs to be a 32-bit int scalar. " << "variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -2741,12 +2748,13 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtDefinition(
[this, &decoration, [this, &decoration,
&inst](const std::string& message) -> spv_result_t { &inst](const std::string& message) -> spv_result_t {
uint32_t vuid = uint32_t vuid =
(spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::Layer) ? 4276 : 4408; (decoration.builtin() == spv::BuiltIn::Layer) ? 4276 : 4408;
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(vuid) << _.VkErrorID(vuid)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< "variable needs to be a 32-bit int scalar. " << "variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -2763,7 +2771,7 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference(
const Decoration& decoration, const Instruction& built_in_inst, const Decoration& decoration, const Instruction& built_in_inst,
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
uint32_t operand = decoration.params()[0]; uint32_t operand = (uint32_t)decoration.builtin();
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
@ -2877,7 +2885,7 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference(
spv_result_t BuiltInsValidator::ValidateFragmentShaderF32Vec3InputAtDefinition( spv_result_t BuiltInsValidator::ValidateFragmentShaderF32Vec3InputAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (spv_result_t error = ValidateF32Vec( if (spv_result_t error = ValidateF32Vec(
decoration, inst, 3, decoration, inst, 3,
[this, &inst, builtin](const std::string& message) -> spv_result_t { [this, &inst, builtin](const std::string& message) -> spv_result_t {
@ -2907,7 +2915,7 @@ spv_result_t BuiltInsValidator::ValidateFragmentShaderF32Vec3InputAtReference(
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input) { storage_class != spv::StorageClass::Input) {
@ -2951,7 +2959,7 @@ spv_result_t BuiltInsValidator::ValidateFragmentShaderF32Vec3InputAtReference(
spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtDefinition( spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (spv_result_t error = ValidateI32Vec( if (spv_result_t error = ValidateI32Vec(
decoration, inst, 3, decoration, inst, 3,
[this, &inst, builtin](const std::string& message) -> spv_result_t { [this, &inst, builtin](const std::string& message) -> spv_result_t {
@ -2980,7 +2988,7 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference(
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input) { storage_class != spv::StorageClass::Input) {
@ -3031,7 +3039,7 @@ spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtReference(
spv_result_t BuiltInsValidator::ValidateComputeI32InputAtDefinition( spv_result_t BuiltInsValidator::ValidateComputeI32InputAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (decoration.struct_member_index() != Decoration::kInvalidMember) { if (decoration.struct_member_index() != Decoration::kInvalidMember) {
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< "BuiltIn " << "BuiltIn "
@ -3065,7 +3073,7 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference(
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input) { storage_class != spv::StorageClass::Input) {
@ -3116,7 +3124,7 @@ spv_result_t BuiltInsValidator::ValidateComputeI32InputAtReference(
spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition( spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (decoration.struct_member_index() != Decoration::kInvalidMember) { if (decoration.struct_member_index() != Decoration::kInvalidMember) {
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< "BuiltIn " << "BuiltIn "
@ -3159,7 +3167,7 @@ spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition( spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (decoration.struct_member_index() != Decoration::kInvalidMember) { if (decoration.struct_member_index() != Decoration::kInvalidMember) {
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< "BuiltIn " << "BuiltIn "
@ -3247,7 +3255,7 @@ spv_result_t BuiltInsValidator::ValidateWorkgroupSizeAtReference(
<< spvLogStringForEnv(_.context()->target_env) << spvLogStringForEnv(_.context()->target_env)
<< " spec allows BuiltIn " << " spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or " << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or "
<< "TaskEXT execution model. " << "TaskEXT execution model. "
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@ -3273,14 +3281,15 @@ spv_result_t BuiltInsValidator::ValidateBaseInstanceOrVertexAtDefinition(
decoration, inst, decoration, inst,
[this, &inst, [this, &inst,
&decoration](const std::string& message) -> spv_result_t { &decoration](const std::string& message) -> spv_result_t {
uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::BaseInstance) uint32_t vuid =
? 4183 (decoration.builtin() == spv::BuiltIn::BaseInstance) ? 4183
: 4186; : 4186;
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(vuid) << _.VkErrorID(vuid)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int scalar. " << " variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -3295,7 +3304,7 @@ spv_result_t BuiltInsValidator::ValidateBaseInstanceOrVertexAtReference(
const Decoration& decoration, const Instruction& built_in_inst, const Decoration& decoration, const Instruction& built_in_inst,
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
uint32_t operand = decoration.params()[0]; uint32_t operand = (uint32_t)decoration.builtin();
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
@ -3346,8 +3355,9 @@ spv_result_t BuiltInsValidator::ValidateDrawIndexAtDefinition(
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(4209) << _.VkErrorID(4209)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int scalar. " << " variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -3362,7 +3372,7 @@ spv_result_t BuiltInsValidator::ValidateDrawIndexAtReference(
const Decoration& decoration, const Instruction& built_in_inst, const Decoration& decoration, const Instruction& built_in_inst,
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
uint32_t operand = decoration.params()[0]; uint32_t operand = (uint32_t)decoration.builtin();
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
@ -3416,8 +3426,9 @@ spv_result_t BuiltInsValidator::ValidateViewIndexAtDefinition(
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(4403) << _.VkErrorID(4403)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int scalar. " << " variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -3432,7 +3443,7 @@ spv_result_t BuiltInsValidator::ValidateViewIndexAtReference(
const Decoration& decoration, const Instruction& built_in_inst, const Decoration& decoration, const Instruction& built_in_inst,
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
uint32_t operand = decoration.params()[0]; uint32_t operand = (uint32_t)decoration.builtin();
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
@ -3480,8 +3491,9 @@ spv_result_t BuiltInsValidator::ValidateDeviceIndexAtDefinition(
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(4206) << _.VkErrorID(4206)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int scalar. " << " variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -3496,7 +3508,7 @@ spv_result_t BuiltInsValidator::ValidateDeviceIndexAtReference(
const Decoration& decoration, const Instruction& built_in_inst, const Decoration& decoration, const Instruction& built_in_inst,
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
uint32_t operand = decoration.params()[0]; uint32_t operand = (uint32_t)decoration.builtin();
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
@ -3526,7 +3538,7 @@ spv_result_t BuiltInsValidator::ValidateFragInvocationCountAtDefinition(const De
const Instruction& inst) { const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (spv_result_t error = ValidateI32( if (spv_result_t error = ValidateI32(
decoration, inst, decoration, inst,
[this, &inst, &builtin](const std::string& message) -> spv_result_t { [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@ -3553,7 +3565,7 @@ spv_result_t BuiltInsValidator::ValidateFragInvocationCountAtReference(
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input) { storage_class != spv::StorageClass::Input) {
@ -3596,7 +3608,7 @@ spv_result_t BuiltInsValidator::ValidateFragInvocationCountAtReference(
spv_result_t BuiltInsValidator::ValidateFragSizeAtDefinition(const Decoration& decoration, spv_result_t BuiltInsValidator::ValidateFragSizeAtDefinition(const Decoration& decoration,
const Instruction& inst) { const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (spv_result_t error = ValidateI32Vec( if (spv_result_t error = ValidateI32Vec(
decoration, inst, 2, decoration, inst, 2,
[this, &inst, &builtin](const std::string& message) -> spv_result_t { [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@ -3623,7 +3635,7 @@ spv_result_t BuiltInsValidator::ValidateFragSizeAtReference(
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input) { storage_class != spv::StorageClass::Input) {
@ -3666,7 +3678,7 @@ spv_result_t BuiltInsValidator::ValidateFragSizeAtReference(
spv_result_t BuiltInsValidator::ValidateFragStencilRefAtDefinition(const Decoration& decoration, spv_result_t BuiltInsValidator::ValidateFragStencilRefAtDefinition(const Decoration& decoration,
const Instruction& inst) { const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (spv_result_t error = ValidateI( if (spv_result_t error = ValidateI(
decoration, inst, decoration, inst,
[this, &inst, &builtin](const std::string& message) -> spv_result_t { [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@ -3693,7 +3705,7 @@ spv_result_t BuiltInsValidator::ValidateFragStencilRefAtReference(
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Output) { storage_class != spv::StorageClass::Output) {
@ -3736,7 +3748,7 @@ spv_result_t BuiltInsValidator::ValidateFragStencilRefAtReference(
spv_result_t BuiltInsValidator::ValidateFullyCoveredAtDefinition(const Decoration& decoration, spv_result_t BuiltInsValidator::ValidateFullyCoveredAtDefinition(const Decoration& decoration,
const Instruction& inst) { const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
if (spv_result_t error = ValidateBool( if (spv_result_t error = ValidateBool(
decoration, inst, decoration, inst,
[this, &inst, &builtin](const std::string& message) -> spv_result_t { [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@ -3763,7 +3775,7 @@ spv_result_t BuiltInsValidator::ValidateFullyCoveredAtReference(
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input) { storage_class != spv::StorageClass::Input) {
@ -3814,8 +3826,9 @@ spv_result_t BuiltInsValidator::ValidateNVSMOrARMCoreBuiltinsAtDefinition(
<< "According to the " << "According to the "
<< spvLogStringForEnv(_.context()->target_env) << spvLogStringForEnv(_.context()->target_env)
<< " spec BuiltIn " << " spec BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int scalar. " << " variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -3839,7 +3852,7 @@ spv_result_t BuiltInsValidator::ValidateNVSMOrARMCoreBuiltinsAtReference(
<< spvLogStringForEnv(_.context()->target_env) << spvLogStringForEnv(_.context()->target_env)
<< " spec allows BuiltIn " << " spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " to be only used for " << " to be only used for "
"variables with Input storage class. " "variables with Input storage class. "
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@ -3868,8 +3881,9 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtDefinition(
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(4486) << _.VkErrorID(4486)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int scalar. " << " variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -3892,7 +3906,7 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtReference(
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(4485) << "Vulkan spec allows BuiltIn " << _.VkErrorID(4485) << "Vulkan spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " to be only used for variables with Output storage class. " << " to be only used for variables with Output storage class. "
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
referenced_from_inst) referenced_from_inst)
@ -3909,8 +3923,9 @@ spv_result_t BuiltInsValidator::ValidatePrimitiveShadingRateAtReference(
default: { default: {
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(4484) << "Vulkan spec allows BuiltIn " << _.VkErrorID(4484) << "Vulkan spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " to be used only with Vertex, Geometry, or MeshNV " << " to be used only with Vertex, Geometry, or MeshNV "
"execution models. " "execution models. "
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@ -3941,8 +3956,9 @@ spv_result_t BuiltInsValidator::ValidateShadingRateAtDefinition(
return _.diag(SPV_ERROR_INVALID_DATA, &inst) return _.diag(SPV_ERROR_INVALID_DATA, &inst)
<< _.VkErrorID(4492) << _.VkErrorID(4492)
<< "According to the Vulkan spec BuiltIn " << "According to the Vulkan spec BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(
decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int scalar. " << " variable needs to be a 32-bit int scalar. "
<< message; << message;
})) { })) {
@ -3965,7 +3981,7 @@ spv_result_t BuiltInsValidator::ValidateShadingRateAtReference(
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(4491) << "Vulkan spec allows BuiltIn " << _.VkErrorID(4491) << "Vulkan spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " to be only used for variables with Input storage class. " << " to be only used for variables with Input storage class. "
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
referenced_from_inst) referenced_from_inst)
@ -3977,7 +3993,7 @@ spv_result_t BuiltInsValidator::ValidateShadingRateAtReference(
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(4490) << "Vulkan spec allows BuiltIn " << _.VkErrorID(4490) << "Vulkan spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " to be used only with the Fragment execution model. " << " to be used only with the Fragment execution model. "
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
referenced_from_inst, execution_model); referenced_from_inst, execution_model);
@ -3998,7 +4014,7 @@ spv_result_t BuiltInsValidator::ValidateShadingRateAtReference(
spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition( spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
switch (builtin) { switch (builtin) {
case spv::BuiltIn::HitTNV: case spv::BuiltIn::HitTNV:
case spv::BuiltIn::RayTminKHR: case spv::BuiltIn::RayTminKHR:
@ -4121,7 +4137,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst); const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
storage_class != spv::StorageClass::Input) { storage_class != spv::StorageClass::Input) {
@ -4129,7 +4145,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn " << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " to be only used for variables with Input storage class. " << " to be only used for variables with Input storage class. "
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
referenced_from_inst) referenced_from_inst)
@ -4142,10 +4158,11 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst) return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
<< _.VkErrorID(vuid) << "Vulkan spec does not allow BuiltIn " << _.VkErrorID(vuid) << "Vulkan spec does not allow BuiltIn "
<< _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
decoration.params()[0]) (uint32_t)decoration.builtin())
<< " to be used with the execution model " << " to be used with the execution model "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_EXECUTION_MODEL, uint32_t(execution_model)) SPV_OPERAND_TYPE_EXECUTION_MODEL,
uint32_t(execution_model))
<< ".\n" << ".\n"
<< GetReferenceDesc(decoration, built_in_inst, referenced_inst, << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
referenced_from_inst, execution_model); referenced_from_inst, execution_model);
@ -4167,7 +4184,7 @@ spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtReference(
spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition( spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType); uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorType);
if (builtin == spv::BuiltIn::PrimitivePointIndicesEXT) { if (builtin == spv::BuiltIn::PrimitivePointIndicesEXT) {
if (spv_result_t error = ValidateI32Arr( if (spv_result_t error = ValidateI32Arr(
@ -4179,7 +4196,8 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
<< spvLogStringForEnv(_.context()->target_env) << spvLogStringForEnv(_.context()->target_env)
<< " spec BuiltIn " << " spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 32-bit int array." << " variable needs to be a 32-bit int array."
<< message; << message;
})) { })) {
@ -4196,7 +4214,8 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
<< spvLogStringForEnv(_.context()->target_env) << spvLogStringForEnv(_.context()->target_env)
<< " spec BuiltIn " << " spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 2-component 32-bit int " << " variable needs to be a 2-component 32-bit int "
"array." "array."
<< message; << message;
@ -4214,7 +4233,8 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtDefinition(
<< spvLogStringForEnv(_.context()->target_env) << spvLogStringForEnv(_.context()->target_env)
<< " spec BuiltIn " << " spec BuiltIn "
<< _.grammar().lookupOperandName( << _.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]) SPV_OPERAND_TYPE_BUILT_IN,
(uint32_t)decoration.builtin())
<< " variable needs to be a 3-component 32-bit int " << " variable needs to be a 3-component 32-bit int "
"array." "array."
<< message; << message;
@ -4233,7 +4253,7 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtReference(
const Instruction& referenced_inst, const Instruction& referenced_inst,
const Instruction& referenced_from_inst) { const Instruction& referenced_from_inst) {
if (spvIsVulkanEnv(_.context()->target_env)) { if (spvIsVulkanEnv(_.context()->target_env)) {
const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn builtin = decoration.builtin();
const spv::StorageClass storage_class = const spv::StorageClass storage_class =
GetStorageClass(referenced_from_inst); GetStorageClass(referenced_from_inst);
if (storage_class != spv::StorageClass::Max && if (storage_class != spv::StorageClass::Max &&
@ -4279,7 +4299,7 @@ spv_result_t BuiltInsValidator::ValidateMeshShadingEXTBuiltinsAtReference(
spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition( spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
const Decoration& decoration, const Instruction& inst) { const Decoration& decoration, const Instruction& inst) {
const spv::BuiltIn label = spv::BuiltIn(decoration.params()[0]); const spv::BuiltIn label = decoration.builtin();
if (!spvIsVulkanEnv(_.context()->target_env)) { if (!spvIsVulkanEnv(_.context()->target_env)) {
// Early return. All currently implemented rules are based on Vulkan spec. // Early return. All currently implemented rules are based on Vulkan spec.

View File

@ -71,26 +71,6 @@ uint32_t GetArrayStride(uint32_t array_id, ValidationState_t& vstate) {
return 0; return 0;
} }
// Returns true if the given variable has a BuiltIn decoration.
bool isBuiltInVar(uint32_t var_id, ValidationState_t& vstate) {
const auto& decorations = vstate.id_decorations(var_id);
return std::any_of(decorations.begin(), decorations.end(),
[](const Decoration& d) {
return spv::Decoration::BuiltIn == d.dec_type();
});
}
// Returns true if the given structure type has any members with BuiltIn
// decoration.
bool isBuiltInStruct(uint32_t struct_id, ValidationState_t& vstate) {
const auto& decorations = vstate.id_decorations(struct_id);
return std::any_of(
decorations.begin(), decorations.end(), [](const Decoration& d) {
return spv::Decoration::BuiltIn == d.dec_type() &&
Decoration::kInvalidMember != d.struct_member_index();
});
}
// Returns true if the given structure type has a Block decoration. // Returns true if the given structure type has a Block decoration.
bool isBlock(uint32_t struct_id, ValidationState_t& vstate) { bool isBlock(uint32_t struct_id, ValidationState_t& vstate) {
const auto& decorations = vstate.id_decorations(struct_id); const auto& decorations = vstate.id_decorations(struct_id);
@ -786,6 +766,8 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
int num_workgroup_variables_with_aliased = 0; int num_workgroup_variables_with_aliased = 0;
for (const auto& desc : descs) { for (const auto& desc : descs) {
std::unordered_set<Instruction*> seen_vars; std::unordered_set<Instruction*> seen_vars;
std::unordered_set<spv::BuiltIn> input_var_builtin;
std::unordered_set<spv::BuiltIn> output_var_builtin;
for (auto interface : desc.interfaces) { for (auto interface : desc.interfaces) {
Instruction* var_instr = vstate.FindDef(interface); Instruction* var_instr = vstate.FindDef(interface);
if (!var_instr || spv::Op::OpVariable != var_instr->opcode()) { if (!var_instr || spv::Op::OpVariable != var_instr->opcode()) {
@ -829,33 +811,70 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
// to. // to.
const uint32_t type_id = ptr_instr->word(3); const uint32_t type_id = ptr_instr->word(3);
Instruction* type_instr = vstate.FindDef(type_id); Instruction* type_instr = vstate.FindDef(type_id);
if (type_instr && spv::Op::OpTypeStruct == type_instr->opcode() && const bool is_struct =
isBuiltInStruct(type_id, vstate)) { type_instr && spv::Op::OpTypeStruct == type_instr->opcode();
if (!isBlock(type_id, vstate)) {
return vstate.diag(SPV_ERROR_INVALID_DATA, vstate.FindDef(type_id)) // Search all Built-in (on the variable or the struct)
<< vstate.VkErrorID(4919) bool has_built_in = false;
<< "Interface struct has no Block decoration but has " for (auto& dec :
"BuiltIn members. " vstate.id_decorations(is_struct ? type_id : interface)) {
"Location decorations must be used on each member of " if (dec.dec_type() != spv::Decoration::BuiltIn) continue;
"OpVariable with a structure type that is a block not " has_built_in = true;
"decorated with Location.";
if (!spvIsVulkanEnv(vstate.context()->target_env)) continue;
const spv::BuiltIn builtin = dec.builtin();
if (storage_class == spv::StorageClass::Input) {
if (!input_var_builtin.insert(builtin).second) {
return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
<< vstate.VkErrorID(9658)
<< "OpEntryPoint contains duplicate input variables "
"with "
<< vstate.grammar().lookupOperandName(
SPV_OPERAND_TYPE_BUILT_IN, (uint32_t)builtin)
<< " builtin";
}
} }
if (storage_class == spv::StorageClass::Input) if (storage_class == spv::StorageClass::Output) {
++num_builtin_block_inputs; if (!output_var_builtin.insert(builtin).second) {
if (storage_class == spv::StorageClass::Output) return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
++num_builtin_block_outputs; << vstate.VkErrorID(9659)
if (num_builtin_block_inputs > 1 || num_builtin_block_outputs > 1) << "OpEntryPoint contains duplicate output variables "
break; "with "
if (auto error = CheckBuiltInVariable(interface, vstate)) << vstate.grammar().lookupOperandName(
return error; SPV_OPERAND_TYPE_BUILT_IN, (uint32_t)builtin)
} else if (isBuiltInVar(interface, vstate)) { << " builtin";
}
}
}
if (has_built_in) {
if (auto error = CheckBuiltInVariable(interface, vstate)) if (auto error = CheckBuiltInVariable(interface, vstate))
return error; return error;
if (is_struct) {
if (!isBlock(type_id, vstate)) {
return vstate.diag(SPV_ERROR_INVALID_DATA,
vstate.FindDef(type_id))
<< vstate.VkErrorID(4919)
<< "Interface struct has no Block decoration but has "
"BuiltIn members. "
"Location decorations must be used on each member of "
"OpVariable with a structure type that is a block not "
"decorated with Location.";
}
if (storage_class == spv::StorageClass::Input)
++num_builtin_block_inputs;
if (storage_class == spv::StorageClass::Output)
++num_builtin_block_outputs;
if (num_builtin_block_inputs > 1 || num_builtin_block_outputs > 1)
break;
}
} }
if (storage_class == spv::StorageClass::Workgroup) { if (storage_class == spv::StorageClass::Workgroup) {
++num_workgroup_variables; ++num_workgroup_variables;
if (type_instr && spv::Op::OpTypeStruct == type_instr->opcode()) { if (is_struct) {
if (hasDecoration(type_id, spv::Decoration::Block, vstate)) if (hasDecoration(type_id, spv::Decoration::Block, vstate))
++num_workgroup_variables_with_block; ++num_workgroup_variables_with_block;
if (hasDecoration(var_instr->id(), spv::Decoration::Aliased, if (hasDecoration(var_instr->id(), spv::Decoration::Aliased,
@ -1665,6 +1684,7 @@ spv_result_t CheckIntegerWrapDecoration(ValidationState_t& vstate,
case spv::Op::OpSNegate: case spv::Op::OpSNegate:
return SPV_SUCCESS; return SPV_SUCCESS;
case spv::Op::OpExtInst: case spv::Op::OpExtInst:
case spv::Op::OpExtInstWithForwardRefsKHR:
// TODO(dneto): Only certain extended instructions allow these // TODO(dneto): Only certain extended instructions allow these
// decorations. For now allow anything. // decorations. For now allow anything.
return SPV_SUCCESS; return SPV_SUCCESS;

View File

@ -147,7 +147,7 @@ bool DoesDebugInfoOperandMatchExpectation(
const Instruction* inst, uint32_t word_index) { const Instruction* inst, uint32_t word_index) {
if (inst->words().size() <= word_index) return false; if (inst->words().size() <= word_index) return false;
auto* debug_inst = _.FindDef(inst->word(word_index)); auto* debug_inst = _.FindDef(inst->word(word_index));
if (debug_inst->opcode() != spv::Op::OpExtInst || if (!spvIsExtendedInstruction(debug_inst->opcode()) ||
(debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 && (debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 &&
debug_inst->ext_inst_type() != debug_inst->ext_inst_type() !=
SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) || SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
@ -165,7 +165,7 @@ bool DoesDebugInfoOperandMatchExpectation(
const Instruction* inst, uint32_t word_index) { const Instruction* inst, uint32_t word_index) {
if (inst->words().size() <= word_index) return false; if (inst->words().size() <= word_index) return false;
auto* debug_inst = _.FindDef(inst->word(word_index)); auto* debug_inst = _.FindDef(inst->word(word_index));
if (debug_inst->opcode() != spv::Op::OpExtInst || if (!spvIsExtendedInstruction(debug_inst->opcode()) ||
(debug_inst->ext_inst_type() != (debug_inst->ext_inst_type() !=
SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) || SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
!expectation( !expectation(
@ -409,7 +409,7 @@ spv_result_t ValidateClspvReflectionArgumentInfo(ValidationState_t& _,
spv_result_t ValidateKernelDecl(ValidationState_t& _, const Instruction* inst) { spv_result_t ValidateKernelDecl(ValidationState_t& _, const Instruction* inst) {
const auto decl_id = inst->GetOperandAs<uint32_t>(4); const auto decl_id = inst->GetOperandAs<uint32_t>(4);
const auto decl = _.FindDef(decl_id); const auto decl = _.FindDef(decl_id);
if (!decl || decl->opcode() != spv::Op::OpExtInst) { if (!decl || !spvIsExtendedInstruction(decl->opcode())) {
return _.diag(SPV_ERROR_INVALID_ID, inst) return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "Kernel must be a Kernel extended instruction"; << "Kernel must be a Kernel extended instruction";
} }
@ -432,7 +432,7 @@ spv_result_t ValidateKernelDecl(ValidationState_t& _, const Instruction* inst) {
spv_result_t ValidateArgInfo(ValidationState_t& _, const Instruction* inst, spv_result_t ValidateArgInfo(ValidationState_t& _, const Instruction* inst,
uint32_t info_index) { uint32_t info_index) {
auto info = _.FindDef(inst->GetOperandAs<uint32_t>(info_index)); auto info = _.FindDef(inst->GetOperandAs<uint32_t>(info_index));
if (!info || info->opcode() != spv::Op::OpExtInst) { if (!info || !spvIsExtendedInstruction(info->opcode())) {
return _.diag(SPV_ERROR_INVALID_ID, inst) return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "ArgInfo must be an ArgumentInfo extended instruction"; << "ArgInfo must be an ArgumentInfo extended instruction";
} }
@ -3706,7 +3706,7 @@ spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
const spv::Op opcode = inst->opcode(); const spv::Op opcode = inst->opcode();
if (opcode == spv::Op::OpExtension) return ValidateExtension(_, inst); if (opcode == spv::Op::OpExtension) return ValidateExtension(_, inst);
if (opcode == spv::Op::OpExtInstImport) return ValidateExtInstImport(_, inst); if (opcode == spv::Op::OpExtInstImport) return ValidateExtInstImport(_, inst);
if (opcode == spv::Op::OpExtInst) return ValidateExtInst(_, inst); if (spvIsExtendedInstruction(opcode)) return ValidateExtInst(_, inst);
return SPV_SUCCESS; return SPV_SUCCESS;
} }

View File

@ -120,15 +120,16 @@ spv_result_t CheckIdDefinitionDominateUse(ValidationState_t& _) {
// instruction operand's ID can be forward referenced. // instruction operand's ID can be forward referenced.
spv_result_t IdPass(ValidationState_t& _, Instruction* inst) { spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
auto can_have_forward_declared_ids = auto can_have_forward_declared_ids =
inst->opcode() == spv::Op::OpExtInst && spvIsExtendedInstruction(inst->opcode()) &&
spvExtInstIsDebugInfo(inst->ext_inst_type()) spvExtInstIsDebugInfo(inst->ext_inst_type())
? spvDbgInfoExtOperandCanBeForwardDeclaredFunction( ? spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
inst->ext_inst_type(), inst->word(4)) inst->opcode(), inst->ext_inst_type(), inst->word(4))
: spvOperandCanBeForwardDeclaredFunction(inst->opcode()); : spvOperandCanBeForwardDeclaredFunction(inst->opcode());
// Keep track of a result id defined by this instruction. 0 means it // Keep track of a result id defined by this instruction. 0 means it
// does not define an id. // does not define an id.
uint32_t result_id = 0; uint32_t result_id = 0;
bool has_forward_declared_ids = false;
for (unsigned i = 0; i < inst->operands().size(); i++) { for (unsigned i = 0; i < inst->operands().size(); i++) {
const spv_parsed_operand_t& operand = inst->operand(i); const spv_parsed_operand_t& operand = inst->operand(i);
@ -177,6 +178,7 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
!inst->IsNonSemantic() && !spvOpcodeIsDecoration(opcode) && !inst->IsNonSemantic() && !spvOpcodeIsDecoration(opcode) &&
!spvOpcodeIsBranch(opcode) && opcode != spv::Op::OpPhi && !spvOpcodeIsBranch(opcode) && opcode != spv::Op::OpPhi &&
opcode != spv::Op::OpExtInst && opcode != spv::Op::OpExtInst &&
opcode != spv::Op::OpExtInstWithForwardRefsKHR &&
opcode != spv::Op::OpExtInstImport && opcode != spv::Op::OpExtInstImport &&
opcode != spv::Op::OpSelectionMerge && opcode != spv::Op::OpSelectionMerge &&
opcode != spv::Op::OpLoopMerge && opcode != spv::Op::OpLoopMerge &&
@ -200,6 +202,7 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
ret = SPV_SUCCESS; ret = SPV_SUCCESS;
} }
} else if (can_have_forward_declared_ids(i)) { } else if (can_have_forward_declared_ids(i)) {
has_forward_declared_ids = true;
if (spvOpcodeGeneratesType(inst->opcode()) && if (spvOpcodeGeneratesType(inst->opcode()) &&
!_.IsForwardPointer(operand_word)) { !_.IsForwardPointer(operand_word)) {
ret = _.diag(SPV_ERROR_INVALID_ID, inst) ret = _.diag(SPV_ERROR_INVALID_ID, inst)
@ -229,12 +232,35 @@ spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
<< " has not been defined"; << " has not been defined";
} }
break; break;
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
// Ideally, this check would live in validate_extensions.cpp. But since
// forward references are only allowed on non-semantic instructions, and
// ID validation is done first, we would fail with a "ID had not been
// defined" error before we could give a more helpful message. For this
// reason, this test is done here, so we can be more helpful to the
// user.
if (inst->opcode() == spv::Op::OpExtInstWithForwardRefsKHR &&
!inst->IsNonSemantic())
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< "OpExtInstWithForwardRefsKHR is only allowed with "
"non-semantic instructions.";
ret = SPV_SUCCESS;
break;
default: default:
ret = SPV_SUCCESS; ret = SPV_SUCCESS;
break; break;
} }
if (SPV_SUCCESS != ret) return ret; if (SPV_SUCCESS != ret) return ret;
} }
const bool must_have_forward_declared_ids =
inst->opcode() == spv::Op::OpExtInstWithForwardRefsKHR;
if (must_have_forward_declared_ids && !has_forward_declared_ids) {
return _.diag(SPV_ERROR_INVALID_ID, inst)
<< "Opcode OpExtInstWithForwardRefsKHR must have at least one "
"forward "
"declared ID.";
}
if (result_id) _.RemoveIfForwardDeclared(result_id); if (result_id) _.RemoveIfForwardDeclared(result_id);
return SPV_SUCCESS; return SPV_SUCCESS;

View File

@ -1005,7 +1005,8 @@ bool IsAllowedSampledImageOperand(spv::Op opcode, ValidationState_t& _) {
spv_result_t ValidateSampledImage(ValidationState_t& _, spv_result_t ValidateSampledImage(ValidationState_t& _,
const Instruction* inst) { const Instruction* inst) {
if (_.GetIdOpcode(inst->type_id()) != spv::Op::OpTypeSampledImage) { auto type_inst = _.FindDef(inst->type_id());
if (type_inst->opcode() != spv::Op::OpTypeSampledImage) {
return _.diag(SPV_ERROR_INVALID_DATA, inst) return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< "Expected Result Type to be OpTypeSampledImage."; << "Expected Result Type to be OpTypeSampledImage.";
} }
@ -1016,6 +1017,11 @@ spv_result_t ValidateSampledImage(ValidationState_t& _,
<< "Expected Image to be of type OpTypeImage."; << "Expected Image to be of type OpTypeImage.";
} }
if (type_inst->GetOperandAs<uint32_t>(1) != image_type) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< "Expected Image to have the same type as Result Type Image";
}
ImageTypeInfo info; ImageTypeInfo info;
if (!GetImageTypeInfo(_, image_type, &info)) { if (!GetImageTypeInfo(_, image_type, &info)) {
return _.diag(SPV_ERROR_INVALID_DATA, inst) return _.diag(SPV_ERROR_INVALID_DATA, inst)

View File

@ -35,6 +35,7 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _,
const Instruction* inst, spv::Op opcode) { const Instruction* inst, spv::Op opcode) {
switch (opcode) { switch (opcode) {
case spv::Op::OpExtInst: case spv::Op::OpExtInst:
case spv::Op::OpExtInstWithForwardRefsKHR:
if (spvExtInstIsDebugInfo(inst->ext_inst_type())) { if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
const uint32_t ext_inst_index = inst->word(4); const uint32_t ext_inst_index = inst->word(4);
bool local_debug_info = false; bool local_debug_info = false;
@ -243,6 +244,7 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _,
break; break;
case spv::Op::OpExtInst: case spv::Op::OpExtInst:
case spv::Op::OpExtInstWithForwardRefsKHR:
if (spvExtInstIsDebugInfo(inst->ext_inst_type())) { if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
const uint32_t ext_inst_index = inst->word(4); const uint32_t ext_inst_index = inst->word(4);
bool local_debug_info = false; bool local_debug_info = false;

View File

@ -76,6 +76,7 @@ ModuleLayoutSection InstructionLayoutSection(
if (current_section == kLayoutTypes) return kLayoutTypes; if (current_section == kLayoutTypes) return kLayoutTypes;
return kLayoutFunctionDefinitions; return kLayoutFunctionDefinitions;
case spv::Op::OpExtInst: case spv::Op::OpExtInst:
case spv::Op::OpExtInstWithForwardRefsKHR:
// spv::Op::OpExtInst is only allowed in types section for certain // spv::Op::OpExtInst is only allowed in types section for certain
// extended instruction sets. This will be checked separately. // extended instruction sets. This will be checked separately.
if (current_section == kLayoutTypes) return kLayoutTypes; if (current_section == kLayoutTypes) return kLayoutTypes;
@ -2353,6 +2354,10 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
return VUID_WRAP(VUID-StandaloneSpirv-Pointer-08973); return VUID_WRAP(VUID-StandaloneSpirv-Pointer-08973);
case 9638: case 9638:
return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-09638); return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-09638);
case 9658:
return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-09658);
case 9659:
return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-09659);
default: default:
return ""; // unknown id return ""; // unknown id
} }