mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-tools.
This commit is contained in:
@@ -1 +1 @@
|
||||
"v2021.5-dev", "SPIRV-Tools v2021.5-dev 73acc9e59b165d08e3b418d207d84abd46cca49c"
|
||||
"v2021.5-dev", "SPIRV-Tools v2021.5-dev aa79ba8a396f8da0e5bed8c03e72cf0cfd99d2dc"
|
||||
|
||||
@@ -10,9 +10,11 @@ static const SpvCapability pygen_variable_caps_AtomicFloat16MinMaxEXTAtomicFloat
|
||||
static const SpvCapability pygen_variable_caps_BindlessTextureNV[] = {SpvCapabilityBindlessTextureNV};
|
||||
static const SpvCapability pygen_variable_caps_BlockingPipesINTEL[] = {SpvCapabilityBlockingPipesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_CooperativeMatrixNV[] = {SpvCapabilityCooperativeMatrixNV};
|
||||
static const SpvCapability pygen_variable_caps_DemoteToHelperInvocation[] = {SpvCapabilityDemoteToHelperInvocation};
|
||||
static const SpvCapability pygen_variable_caps_DemoteToHelperInvocationEXT[] = {SpvCapabilityDemoteToHelperInvocationEXT};
|
||||
static const SpvCapability pygen_variable_caps_DerivativeControl[] = {SpvCapabilityDerivativeControl};
|
||||
static const SpvCapability pygen_variable_caps_DeviceEnqueue[] = {SpvCapabilityDeviceEnqueue};
|
||||
static const SpvCapability pygen_variable_caps_DotProduct[] = {SpvCapabilityDotProduct};
|
||||
static const SpvCapability pygen_variable_caps_DotProductKHR[] = {SpvCapabilityDotProductKHR};
|
||||
static const SpvCapability pygen_variable_caps_ExpectAssumeKHR[] = {SpvCapabilityExpectAssumeKHR};
|
||||
static const SpvCapability pygen_variable_caps_FPGARegINTEL[] = {SpvCapabilityFPGARegINTEL};
|
||||
@@ -80,6 +82,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_reg[] = {spv
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_function_pointers[] = {spvtools::Extension::kSPV_INTEL_function_pointers};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_unstructured_loop_controls[] = {spvtools::Extension::kSPV_INTEL_unstructured_loop_controls};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_expect_assume[] = {spvtools::Extension::kSPV_KHR_expect_assume};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_integer_dot_product[] = {spvtools::Extension::kSPV_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_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};
|
||||
@@ -246,7 +249,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"IsFinite", SpvOpIsFinite, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"IsNormal", SpvOpIsNormal, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"SignBitSet", SpvOpSignBitSet, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"LessOrGreater", SpvOpLessOrGreater, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"LessOrGreater", SpvOpLessOrGreater, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), SPV_SPIRV_VERSION_WORD(1,5)},
|
||||
{"Ordered", SpvOpOrdered, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"Unordered", SpvOpUnordered, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"LogicalEqual", SpvOpLogicalEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
@@ -441,7 +444,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"PtrEqual", SpvOpPtrEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"PtrNotEqual", SpvOpPtrNotEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"PtrDiff", SpvOpPtrDiff, 3, pygen_variable_caps_AddressesVariablePointersVariablePointersStorageBuffer, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"TerminateInvocation", SpvOpTerminateInvocation, 1, pygen_variable_caps_Shader, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_KHR_terminate_invocation, 0xffffffffu, 0xffffffffu},
|
||||
{"TerminateInvocation", SpvOpTerminateInvocation, 1, pygen_variable_caps_Shader, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_KHR_terminate_invocation, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SubgroupBallotKHR", SpvOpSubgroupBallotKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupFirstInvocationKHR", SpvOpSubgroupFirstInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupAllKHR", SpvOpSubgroupAllKHR, 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},
|
||||
@@ -453,12 +456,18 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"ConvertUToAccelerationStructureKHR", SpvOpConvertUToAccelerationStructureKHR, 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},
|
||||
{"IgnoreIntersectionKHR", SpvOpIgnoreIntersectionKHR, 1, pygen_variable_caps_RayTracingKHR, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu},
|
||||
{"TerminateRayKHR", SpvOpTerminateRayKHR, 1, pygen_variable_caps_RayTracingKHR, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_tracing, 0xffffffffu, 0xffffffffu},
|
||||
{"SDotKHR", SpvOpSDotKHR, 1, pygen_variable_caps_DotProductKHR, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"UDotKHR", SpvOpUDotKHR, 1, pygen_variable_caps_DotProductKHR, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"SUDotKHR", SpvOpSUDotKHR, 1, pygen_variable_caps_DotProductKHR, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"SDotAccSatKHR", SpvOpSDotAccSatKHR, 1, pygen_variable_caps_DotProductKHR, 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_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"UDotAccSatKHR", SpvOpUDotAccSatKHR, 1, pygen_variable_caps_DotProductKHR, 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_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"SUDotAccSatKHR", SpvOpSUDotAccSatKHR, 1, pygen_variable_caps_DotProductKHR, 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_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"SDot", SpvOpSDot, 1, pygen_variable_caps_DotProduct, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SDotKHR", SpvOpSDotKHR, 1, pygen_variable_caps_DotProductKHR, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"UDot", SpvOpUDot, 1, pygen_variable_caps_DotProduct, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"UDotKHR", SpvOpUDotKHR, 1, pygen_variable_caps_DotProductKHR, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SUDot", SpvOpSUDot, 1, pygen_variable_caps_DotProduct, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SUDotKHR", SpvOpSUDotKHR, 1, pygen_variable_caps_DotProductKHR, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT}, 1, 1, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SDotAccSat", SpvOpSDotAccSat, 1, pygen_variable_caps_DotProduct, 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_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SDotAccSatKHR", SpvOpSDotAccSatKHR, 1, pygen_variable_caps_DotProductKHR, 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_PACKED_VECTOR_FORMAT}, 1, 1, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"UDotAccSat", SpvOpUDotAccSat, 1, pygen_variable_caps_DotProduct, 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_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"UDotAccSatKHR", SpvOpUDotAccSatKHR, 1, pygen_variable_caps_DotProductKHR, 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_PACKED_VECTOR_FORMAT}, 1, 1, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SUDotAccSat", SpvOpSUDotAccSat, 1, pygen_variable_caps_DotProduct, 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_PACKED_VECTOR_FORMAT}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"SUDotAccSatKHR", SpvOpSUDotAccSatKHR, 1, pygen_variable_caps_DotProductKHR, 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_PACKED_VECTOR_FORMAT}, 1, 1, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"TypeRayQueryKHR", SpvOpTypeRayQueryKHR, 1, pygen_variable_caps_RayQueryKHR, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
|
||||
{"RayQueryInitializeKHR", SpvOpRayQueryInitializeKHR, 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", SpvOpRayQueryTerminateKHR, 1, pygen_variable_caps_RayQueryKHR, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
|
||||
@@ -497,7 +506,8 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"CooperativeMatrixLengthNV", SpvOpCooperativeMatrixLengthNV, 1, pygen_variable_caps_CooperativeMatrixNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_cooperative_matrix, 0xffffffffu, 0xffffffffu},
|
||||
{"BeginInvocationInterlockEXT", SpvOpBeginInvocationInterlockEXT, 3, pygen_variable_caps_FragmentShaderSampleInterlockEXTFragmentShaderPixelInterlockEXTFragmentShaderShadingRateInterlockEXT, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, 0xffffffffu, 0xffffffffu},
|
||||
{"EndInvocationInterlockEXT", SpvOpEndInvocationInterlockEXT, 3, pygen_variable_caps_FragmentShaderSampleInterlockEXTFragmentShaderPixelInterlockEXTFragmentShaderShadingRateInterlockEXT, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, 0xffffffffu, 0xffffffffu},
|
||||
{"DemoteToHelperInvocationEXT", SpvOpDemoteToHelperInvocationEXT, 1, pygen_variable_caps_DemoteToHelperInvocationEXT, 0, {}, 0, 0, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, 0xffffffffu, 0xffffffffu},
|
||||
{"DemoteToHelperInvocation", SpvOpDemoteToHelperInvocation, 1, pygen_variable_caps_DemoteToHelperInvocation, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DemoteToHelperInvocationEXT", SpvOpDemoteToHelperInvocationEXT, 1, pygen_variable_caps_DemoteToHelperInvocation, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"IsHelperInvocationEXT", SpvOpIsHelperInvocationEXT, 1, pygen_variable_caps_DemoteToHelperInvocationEXT, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, 0xffffffffu, 0xffffffffu},
|
||||
{"ConvertUToImageNV", SpvOpConvertUToImageNV, 1, pygen_variable_caps_BindlessTextureNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
{"ConvertUToSamplerNV", SpvOpConvertUToSamplerNV, 1, pygen_variable_caps_BindlessTextureNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
|
||||
|
||||
@@ -118,6 +118,8 @@ const char* ExtensionToString(Extension extension) {
|
||||
return "SPV_KHR_expect_assume";
|
||||
case Extension::kSPV_KHR_float_controls:
|
||||
return "SPV_KHR_float_controls";
|
||||
case Extension::kSPV_KHR_fragment_shader_barycentric:
|
||||
return "SPV_KHR_fragment_shader_barycentric";
|
||||
case Extension::kSPV_KHR_fragment_shading_rate:
|
||||
return "SPV_KHR_fragment_shading_rate";
|
||||
case Extension::kSPV_KHR_integer_dot_product:
|
||||
@@ -201,8 +203,8 @@ const char* ExtensionToString(Extension extension) {
|
||||
|
||||
|
||||
bool GetExtensionFromString(const char* str, Extension* extension) {
|
||||
static const char* known_ext_strs[] = { "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_atomic_float16_add", "SPV_EXT_shader_atomic_float_add", "SPV_EXT_shader_atomic_float_min_max", "SPV_EXT_shader_image_int64", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_arbitrary_precision_fixed_point", "SPV_INTEL_arbitrary_precision_floating_point", "SPV_INTEL_arbitrary_precision_integers", "SPV_INTEL_blocking_pipes", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "SPV_INTEL_fpga_loop_controls", "SPV_INTEL_fpga_memory_accesses", "SPV_INTEL_fpga_memory_attributes", "SPV_INTEL_fpga_reg", "SPV_INTEL_function_pointers", "SPV_INTEL_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_constant_composite", "SPV_INTEL_loop_fuse", "SPV_INTEL_media_block_io", "SPV_INTEL_optnone", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_INTEL_unstructured_loop_controls", "SPV_INTEL_usm_storage_classes", "SPV_INTEL_variable_length_array", "SPV_INTEL_vector_compute", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_bit_instructions", "SPV_KHR_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_non_semantic_info", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_vote", "SPV_KHR_terminate_invocation", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_KHR_workgroup_memory_explicit_layout", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_bindless_texture", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_ray_tracing_motion_blur", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" };
|
||||
static const Extension known_ext_ids[] = { Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_atomic_float16_add, Extension::kSPV_EXT_shader_atomic_float_add, Extension::kSPV_EXT_shader_atomic_float_min_max, Extension::kSPV_EXT_shader_image_int64, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_arbitrary_precision_fixed_point, Extension::kSPV_INTEL_arbitrary_precision_floating_point, Extension::kSPV_INTEL_arbitrary_precision_integers, Extension::kSPV_INTEL_blocking_pipes, Extension::kSPV_INTEL_debug_module, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_float_controls2, Extension::kSPV_INTEL_fp_fast_math_mode, Extension::kSPV_INTEL_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, Extension::kSPV_INTEL_fpga_loop_controls, Extension::kSPV_INTEL_fpga_memory_accesses, Extension::kSPV_INTEL_fpga_memory_attributes, Extension::kSPV_INTEL_fpga_reg, Extension::kSPV_INTEL_function_pointers, Extension::kSPV_INTEL_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_constant_composite, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_optnone, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_INTEL_unstructured_loop_controls, Extension::kSPV_INTEL_usm_storage_classes, Extension::kSPV_INTEL_variable_length_array, Extension::kSPV_INTEL_vector_compute, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_bit_instructions, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_fragment_shading_rate, Extension::kSPV_KHR_integer_dot_product, Extension::kSPV_KHR_linkonce_odr, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_non_semantic_info, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_uniform_control_flow, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_terminate_invocation, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_KHR_workgroup_memory_explicit_layout, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_bindless_texture, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_ray_tracing_motion_blur, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique };
|
||||
static const char* known_ext_strs[] = { "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_demote_to_helper_invocation", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_fragment_invocation_density", "SPV_EXT_fragment_shader_interlock", "SPV_EXT_physical_storage_buffer", "SPV_EXT_shader_atomic_float16_add", "SPV_EXT_shader_atomic_float_add", "SPV_EXT_shader_atomic_float_min_max", "SPV_EXT_shader_image_int64", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_GOOGLE_user_type", "SPV_INTEL_arbitrary_precision_fixed_point", "SPV_INTEL_arbitrary_precision_floating_point", "SPV_INTEL_arbitrary_precision_integers", "SPV_INTEL_blocking_pipes", "SPV_INTEL_debug_module", "SPV_INTEL_device_side_avc_motion_estimation", "SPV_INTEL_float_controls2", "SPV_INTEL_fp_fast_math_mode", "SPV_INTEL_fpga_buffer_location", "SPV_INTEL_fpga_cluster_attributes", "SPV_INTEL_fpga_loop_controls", "SPV_INTEL_fpga_memory_accesses", "SPV_INTEL_fpga_memory_attributes", "SPV_INTEL_fpga_reg", "SPV_INTEL_function_pointers", "SPV_INTEL_inline_assembly", "SPV_INTEL_io_pipes", "SPV_INTEL_kernel_attributes", "SPV_INTEL_long_constant_composite", "SPV_INTEL_loop_fuse", "SPV_INTEL_media_block_io", "SPV_INTEL_optnone", "SPV_INTEL_shader_integer_functions2", "SPV_INTEL_subgroups", "SPV_INTEL_unstructured_loop_controls", "SPV_INTEL_usm_storage_classes", "SPV_INTEL_variable_length_array", "SPV_INTEL_vector_compute", "SPV_KHR_16bit_storage", "SPV_KHR_8bit_storage", "SPV_KHR_bit_instructions", "SPV_KHR_device_group", "SPV_KHR_expect_assume", "SPV_KHR_float_controls", "SPV_KHR_fragment_shader_barycentric", "SPV_KHR_fragment_shading_rate", "SPV_KHR_integer_dot_product", "SPV_KHR_linkonce_odr", "SPV_KHR_multiview", "SPV_KHR_no_integer_wrap_decoration", "SPV_KHR_non_semantic_info", "SPV_KHR_physical_storage_buffer", "SPV_KHR_post_depth_coverage", "SPV_KHR_ray_query", "SPV_KHR_ray_tracing", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_clock", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_uniform_control_flow", "SPV_KHR_subgroup_vote", "SPV_KHR_terminate_invocation", "SPV_KHR_variable_pointers", "SPV_KHR_vulkan_memory_model", "SPV_KHR_workgroup_memory_explicit_layout", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_bindless_texture", "SPV_NV_compute_shader_derivatives", "SPV_NV_cooperative_matrix", "SPV_NV_fragment_shader_barycentric", "SPV_NV_geometry_shader_passthrough", "SPV_NV_mesh_shader", "SPV_NV_ray_tracing", "SPV_NV_ray_tracing_motion_blur", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_image_footprint", "SPV_NV_shader_sm_builtins", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_shading_rate", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" };
|
||||
static const Extension known_ext_ids[] = { Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_demote_to_helper_invocation, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_fragment_invocation_density, Extension::kSPV_EXT_fragment_shader_interlock, Extension::kSPV_EXT_physical_storage_buffer, Extension::kSPV_EXT_shader_atomic_float16_add, Extension::kSPV_EXT_shader_atomic_float_add, Extension::kSPV_EXT_shader_atomic_float_min_max, Extension::kSPV_EXT_shader_image_int64, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_GOOGLE_user_type, Extension::kSPV_INTEL_arbitrary_precision_fixed_point, Extension::kSPV_INTEL_arbitrary_precision_floating_point, Extension::kSPV_INTEL_arbitrary_precision_integers, Extension::kSPV_INTEL_blocking_pipes, Extension::kSPV_INTEL_debug_module, Extension::kSPV_INTEL_device_side_avc_motion_estimation, Extension::kSPV_INTEL_float_controls2, Extension::kSPV_INTEL_fp_fast_math_mode, Extension::kSPV_INTEL_fpga_buffer_location, Extension::kSPV_INTEL_fpga_cluster_attributes, Extension::kSPV_INTEL_fpga_loop_controls, Extension::kSPV_INTEL_fpga_memory_accesses, Extension::kSPV_INTEL_fpga_memory_attributes, Extension::kSPV_INTEL_fpga_reg, Extension::kSPV_INTEL_function_pointers, Extension::kSPV_INTEL_inline_assembly, Extension::kSPV_INTEL_io_pipes, Extension::kSPV_INTEL_kernel_attributes, Extension::kSPV_INTEL_long_constant_composite, Extension::kSPV_INTEL_loop_fuse, Extension::kSPV_INTEL_media_block_io, Extension::kSPV_INTEL_optnone, Extension::kSPV_INTEL_shader_integer_functions2, Extension::kSPV_INTEL_subgroups, Extension::kSPV_INTEL_unstructured_loop_controls, Extension::kSPV_INTEL_usm_storage_classes, Extension::kSPV_INTEL_variable_length_array, Extension::kSPV_INTEL_vector_compute, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_8bit_storage, Extension::kSPV_KHR_bit_instructions, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_expect_assume, Extension::kSPV_KHR_float_controls, Extension::kSPV_KHR_fragment_shader_barycentric, Extension::kSPV_KHR_fragment_shading_rate, Extension::kSPV_KHR_integer_dot_product, Extension::kSPV_KHR_linkonce_odr, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_no_integer_wrap_decoration, Extension::kSPV_KHR_non_semantic_info, Extension::kSPV_KHR_physical_storage_buffer, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_ray_query, Extension::kSPV_KHR_ray_tracing, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_clock, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_uniform_control_flow, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_terminate_invocation, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_KHR_vulkan_memory_model, Extension::kSPV_KHR_workgroup_memory_explicit_layout, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_bindless_texture, Extension::kSPV_NV_compute_shader_derivatives, Extension::kSPV_NV_cooperative_matrix, Extension::kSPV_NV_fragment_shader_barycentric, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_mesh_shader, Extension::kSPV_NV_ray_tracing, Extension::kSPV_NV_ray_tracing_motion_blur, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_image_footprint, Extension::kSPV_NV_shader_sm_builtins, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_shading_rate, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique };
|
||||
const auto b = std::begin(known_ext_strs);
|
||||
const auto e = std::end(known_ext_strs);
|
||||
const auto found = std::equal_range(
|
||||
@@ -356,6 +358,8 @@ const char* CapabilityToString(SpvCapability capability) {
|
||||
return "ShaderLayer";
|
||||
case SpvCapabilityShaderViewportIndex:
|
||||
return "ShaderViewportIndex";
|
||||
case SpvCapabilityUniformDecoration:
|
||||
return "UniformDecoration";
|
||||
case SpvCapabilityFragmentShadingRateKHR:
|
||||
return "FragmentShadingRateKHR";
|
||||
case SpvCapabilitySubgroupBallotKHR:
|
||||
@@ -446,8 +450,8 @@ const char* CapabilityToString(SpvCapability capability) {
|
||||
return "MeshShadingNV";
|
||||
case SpvCapabilityImageFootprintNV:
|
||||
return "ImageFootprintNV";
|
||||
case SpvCapabilityFragmentBarycentricNV:
|
||||
return "FragmentBarycentricNV";
|
||||
case SpvCapabilityFragmentBarycentricKHR:
|
||||
return "FragmentBarycentricKHR";
|
||||
case SpvCapabilityComputeDerivativeGroupQuadsNV:
|
||||
return "ComputeDerivativeGroupQuadsNV";
|
||||
case SpvCapabilityFragmentDensityEXT:
|
||||
@@ -502,8 +506,8 @@ const char* CapabilityToString(SpvCapability capability) {
|
||||
return "ShaderSMBuiltinsNV";
|
||||
case SpvCapabilityFragmentShaderPixelInterlockEXT:
|
||||
return "FragmentShaderPixelInterlockEXT";
|
||||
case SpvCapabilityDemoteToHelperInvocationEXT:
|
||||
return "DemoteToHelperInvocationEXT";
|
||||
case SpvCapabilityDemoteToHelperInvocation:
|
||||
return "DemoteToHelperInvocation";
|
||||
case SpvCapabilityBindlessTextureNV:
|
||||
return "BindlessTextureNV";
|
||||
case SpvCapabilitySubgroupShuffleINTEL:
|
||||
@@ -582,14 +586,14 @@ const char* CapabilityToString(SpvCapability capability) {
|
||||
return "BlockingPipesINTEL";
|
||||
case SpvCapabilityFPGARegINTEL:
|
||||
return "FPGARegINTEL";
|
||||
case SpvCapabilityDotProductInputAllKHR:
|
||||
return "DotProductInputAllKHR";
|
||||
case SpvCapabilityDotProductInput4x8BitKHR:
|
||||
return "DotProductInput4x8BitKHR";
|
||||
case SpvCapabilityDotProductInput4x8BitPackedKHR:
|
||||
return "DotProductInput4x8BitPackedKHR";
|
||||
case SpvCapabilityDotProductKHR:
|
||||
return "DotProductKHR";
|
||||
case SpvCapabilityDotProductInputAll:
|
||||
return "DotProductInputAll";
|
||||
case SpvCapabilityDotProductInput4x8Bit:
|
||||
return "DotProductInput4x8Bit";
|
||||
case SpvCapabilityDotProductInput4x8BitPacked:
|
||||
return "DotProductInput4x8BitPacked";
|
||||
case SpvCapabilityDotProduct:
|
||||
return "DotProduct";
|
||||
case SpvCapabilityBitInstructions:
|
||||
return "BitInstructions";
|
||||
case SpvCapabilityAtomicFloat32AddEXT:
|
||||
|
||||
@@ -57,6 +57,7 @@ kSPV_KHR_bit_instructions,
|
||||
kSPV_KHR_device_group,
|
||||
kSPV_KHR_expect_assume,
|
||||
kSPV_KHR_float_controls,
|
||||
kSPV_KHR_fragment_shader_barycentric,
|
||||
kSPV_KHR_fragment_shading_rate,
|
||||
kSPV_KHR_integer_dot_product,
|
||||
kSPV_KHR_linkonce_odr,
|
||||
|
||||
@@ -29,4 +29,5 @@
|
||||
{28, "gfx-rs community", "Naga", "gfx-rs community Naga"},
|
||||
{29, "Mikkosoft Productions", "MSP Shader Compiler", "Mikkosoft Productions MSP Shader Compiler"},
|
||||
{30, "SpvGenTwo community", "SpvGenTwo SPIR-V IR Tools", "SpvGenTwo community SpvGenTwo SPIR-V IR Tools"},
|
||||
{31, "Google", "Skia SkSL", "Google Skia SkSL"},
|
||||
{31, "Google", "Skia SkSL", "Google Skia SkSL"},
|
||||
{32, "TornadoVM", "SPIRV Beehive Toolkit", "TornadoVM SPIRV Beehive Toolkit"},
|
||||
@@ -20,7 +20,7 @@ static const SpvCapability pygen_variable_caps_FPGAKernelAttributesINTEL[] = {Sp
|
||||
static const SpvCapability pygen_variable_caps_FPGALoopControlsINTEL[] = {SpvCapabilityFPGALoopControlsINTEL};
|
||||
static const SpvCapability pygen_variable_caps_FPGAMemoryAccessesINTEL[] = {SpvCapabilityFPGAMemoryAccessesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_FPGAMemoryAttributesINTEL[] = {SpvCapabilityFPGAMemoryAttributesINTEL};
|
||||
static const SpvCapability pygen_variable_caps_FragmentBarycentricNV[] = {SpvCapabilityFragmentBarycentricNV};
|
||||
static const SpvCapability pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR[] = {SpvCapabilityFragmentBarycentricNV, SpvCapabilityFragmentBarycentricKHR};
|
||||
static const SpvCapability pygen_variable_caps_FragmentDensityEXTShadingRateNV[] = {SpvCapabilityFragmentDensityEXT, SpvCapabilityShadingRateNV};
|
||||
static const SpvCapability pygen_variable_caps_FragmentFullyCoveredEXT[] = {SpvCapabilityFragmentFullyCoveredEXT};
|
||||
static const SpvCapability pygen_variable_caps_FragmentShaderPixelInterlockEXT[] = {SpvCapabilityFragmentShaderPixelInterlockEXT};
|
||||
@@ -94,6 +94,7 @@ static const SpvCapability pygen_variable_caps_Shader[] = {SpvCapabilityShader};
|
||||
static const SpvCapability pygen_variable_caps_ShaderImageCubeArray[] = {SpvCapabilityShader, SpvCapabilityImageCubeArray};
|
||||
static const SpvCapability pygen_variable_caps_ShaderKernel[] = {SpvCapabilityShader, SpvCapabilityKernel};
|
||||
static const SpvCapability pygen_variable_caps_ShaderKernelImageMSArray[] = {SpvCapabilityShader, SpvCapabilityKernel, SpvCapabilityImageMSArray};
|
||||
static const SpvCapability pygen_variable_caps_ShaderUniformDecoration[] = {SpvCapabilityShader, SpvCapabilityUniformDecoration};
|
||||
static const SpvCapability pygen_variable_caps_ShaderVectorComputeINTEL[] = {SpvCapabilityShader, SpvCapabilityVectorComputeINTEL};
|
||||
static const SpvCapability pygen_variable_caps_ShaderNonUniform[] = {SpvCapabilityShaderNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_ShaderSMBuiltinsNV[] = {SpvCapabilityShaderSMBuiltinsNV};
|
||||
@@ -172,6 +173,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_bit_instructions[]
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_device_group[] = {spvtools::Extension::kSPV_KHR_device_group};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_expect_assume[] = {spvtools::Extension::kSPV_KHR_expect_assume};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_float_controls[] = {spvtools::Extension::kSPV_KHR_float_controls};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric[] = {spvtools::Extension::kSPV_KHR_fragment_shader_barycentric, spvtools::Extension::kSPV_NV_fragment_shader_barycentric};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_fragment_shading_rate[] = {spvtools::Extension::kSPV_KHR_fragment_shading_rate};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_integer_dot_product[] = {spvtools::Extension::kSPV_KHR_integer_dot_product};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_KHR_linkonce_odr[] = {spvtools::Extension::kSPV_KHR_linkonce_odr};
|
||||
@@ -198,7 +200,6 @@ static const spvtools::Extension pygen_variable_exts_SPV_NVX_multiview_per_view_
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_bindless_texture[] = {spvtools::Extension::kSPV_NV_bindless_texture};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_compute_shader_derivatives[] = {spvtools::Extension::kSPV_NV_compute_shader_derivatives};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_cooperative_matrix[] = {spvtools::Extension::kSPV_NV_cooperative_matrix};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_fragment_shader_barycentric[] = {spvtools::Extension::kSPV_NV_fragment_shader_barycentric};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_geometry_shader_passthrough[] = {spvtools::Extension::kSPV_NV_geometry_shader_passthrough};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_mesh_shader[] = {spvtools::Extension::kSPV_NV_mesh_shader};
|
||||
static const spvtools::Extension pygen_variable_exts_SPV_NV_mesh_shaderSPV_NV_viewport_array2[] = {spvtools::Extension::kSPV_NV_mesh_shader, spvtools::Extension::kSPV_NV_viewport_array2};
|
||||
@@ -231,6 +232,7 @@ static const spv_operand_desc_t pygen_variable_ImageOperandsEntries[] = {
|
||||
{"VolatileTexelKHR", 0x0800, 1, pygen_variable_caps_VulkanMemoryModel, 1, pygen_variable_exts_SPV_KHR_vulkan_memory_model, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
|
||||
{"SignExtend", 0x1000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"ZeroExtend", 0x2000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"Nontemporal", 0x4000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"Offsets", 0x10000, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu}
|
||||
};
|
||||
|
||||
@@ -690,8 +692,8 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
|
||||
{"Coherent", 23, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"NonWritable", 24, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"NonReadable", 25, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"Uniform", 26, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"UniformId", 27, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_SCOPE_ID}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"Uniform", 26, 2, pygen_variable_caps_ShaderUniformDecoration, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"UniformId", 27, 2, pygen_variable_caps_ShaderUniformDecoration, 0, nullptr, {SPV_OPERAND_TYPE_SCOPE_ID}, SPV_SPIRV_VERSION_WORD(1,4), 0xffffffffu},
|
||||
{"SaturatedConversion", 28, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"Stream", 29, 1, pygen_variable_caps_GeometryStreams, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
{"Location", 30, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0), 0xffffffffu},
|
||||
@@ -722,7 +724,8 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
|
||||
{"PerPrimitiveNV", 5271, 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, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"PerVertexNV", 5285, 1, pygen_variable_caps_FragmentBarycentricNV, 1, pygen_variable_exts_SPV_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},
|
||||
{"PerVertexNV", 5285, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"NonUniform", 5300, 1, pygen_variable_caps_ShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
|
||||
{"NonUniformEXT", 5300, 1, pygen_variable_caps_ShaderNonUniform, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
|
||||
{"RestrictPointer", 5355, 1, pygen_variable_caps_PhysicalStorageBufferAddresses, 2, pygen_variable_exts_SPV_EXT_physical_storage_bufferSPV_KHR_physical_storage_buffer, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
|
||||
@@ -771,7 +774,8 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
|
||||
{"IOPipeStorageINTEL", 5944, 1, pygen_variable_caps_IOPipesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
|
||||
{"FunctionFloatingPointModeINTEL", 6080, 1, pygen_variable_caps_FunctionFloatControlINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_FPOPERATION_MODE}, 0xffffffffu, 0xffffffffu},
|
||||
{"SingleElementVectorINTEL", 6085, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"VectorComputeCallableFunctionINTEL", 6087, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
|
||||
{"VectorComputeCallableFunctionINTEL", 6087, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"MediaBlockIOINTEL", 6140, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
|
||||
@@ -855,8 +859,10 @@ static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
|
||||
{"LayerPerViewNV", 5279, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"MeshViewCountNV", 5280, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"MeshViewIndicesNV", 5281, 1, pygen_variable_caps_MeshShadingNV, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BaryCoordNV", 5286, 1, pygen_variable_caps_FragmentBarycentricNV, 1, pygen_variable_exts_SPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BaryCoordNoPerspNV", 5287, 1, pygen_variable_caps_FragmentBarycentricNV, 1, pygen_variable_exts_SPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BaryCoordKHR", 5286, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BaryCoordNV", 5286, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BaryCoordNoPerspKHR", 5287, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BaryCoordNoPerspNV", 5287, 2, pygen_variable_caps_FragmentBarycentricNVFragmentBarycentricKHR, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragSizeEXT", 5292, 2, pygen_variable_caps_FragmentDensityEXTShadingRateNV, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentSizeNV", 5292, 2, pygen_variable_caps_ShadingRateNVFragmentDensityEXT, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragInvocationCountEXT", 5293, 2, pygen_variable_caps_FragmentDensityEXTShadingRateNV, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu},
|
||||
@@ -993,6 +999,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"GroupNonUniformQuad", 68, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
|
||||
{"ShaderLayer", 69, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
|
||||
{"ShaderViewportIndex", 70, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,5), 0xffffffffu},
|
||||
{"UniformDecoration", 71, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"FragmentShadingRateKHR", 4422, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_fragment_shading_rate, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupBallotKHR", 4423, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3), 0xffffffffu},
|
||||
@@ -1041,7 +1048,8 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"FragmentFullyCoveredEXT", 5265, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_fully_covered, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"MeshShadingNV", 5266, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_NV_mesh_shader, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ImageFootprintNV", 5282, 0, nullptr, 1, pygen_variable_exts_SPV_NV_shader_image_footprint, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentBarycentricNV", 5284, 0, nullptr, 1, pygen_variable_exts_SPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentBarycentricKHR", 5284, 0, nullptr, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentBarycentricNV", 5284, 0, nullptr, 2, pygen_variable_exts_SPV_KHR_fragment_shader_barycentricSPV_NV_fragment_shader_barycentric, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ComputeDerivativeGroupQuadsNV", 5288, 0, nullptr, 1, pygen_variable_exts_SPV_NV_compute_shader_derivatives, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentDensityEXT", 5291, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ShadingRateNV", 5291, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_EXT_fragment_invocation_densitySPV_NV_shading_rate, {}, 0xffffffffu, 0xffffffffu},
|
||||
@@ -1085,7 +1093,8 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"FragmentShaderShadingRateInterlockEXT", 5372, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"ShaderSMBuiltinsNV", 5373, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_NV_shader_sm_builtins, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FragmentShaderPixelInterlockEXT", 5378, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_shader_interlock, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DemoteToHelperInvocationEXT", 5379, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DemoteToHelperInvocation", 5379, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DemoteToHelperInvocationEXT", 5379, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_demote_to_helper_invocation, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"BindlessTextureNV", 5390, 0, nullptr, 1, pygen_variable_exts_SPV_NV_bindless_texture, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupShuffleINTEL", 5568, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"SubgroupBufferBlockIOINTEL", 5569, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu, 0xffffffffu},
|
||||
@@ -1125,16 +1134,20 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"IOPipesINTEL", 5943, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_io_pipes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"BlockingPipesINTEL", 5945, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_blocking_pipes, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"FPGARegINTEL", 5948, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_reg, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DotProductInputAllKHR", 6016, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DotProductInput4x8BitKHR", 6017, 1, pygen_variable_caps_Int8, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DotProductInput4x8BitPackedKHR", 6018, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DotProductKHR", 6019, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DotProductInputAll", 6016, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DotProductInputAllKHR", 6016, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DotProductInput4x8Bit", 6017, 1, pygen_variable_caps_Int8, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DotProductInput4x8BitKHR", 6017, 1, pygen_variable_caps_Int8, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DotProductInput4x8BitPacked", 6018, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DotProductInput4x8BitPackedKHR", 6018, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"DotProduct", 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},
|
||||
{"BitInstructions", 6025, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_bit_instructions, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"AtomicFloat32AddEXT", 6033, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"AtomicFloat64AddEXT", 6034, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"AtomicFloat32AddEXT", 6033, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"AtomicFloat64AddEXT", 6034, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"LongConstantCompositeINTEL", 6089, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_long_constant_composite, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"OptNoneINTEL", 6094, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_optnone, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"AtomicFloat16AddEXT", 6095, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float16_add, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"AtomicFloat16AddEXT", 6095, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float16_add, {}, 0xffffffffu, 0xffffffffu},
|
||||
{"DebugInfoModuleINTEL", 6114, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_debug_module, {}, 0xffffffffu, 0xffffffffu}
|
||||
};
|
||||
|
||||
@@ -1155,7 +1168,8 @@ static const spv_operand_desc_t pygen_variable_RayQueryCandidateIntersectionType
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_PackedVectorFormatEntries[] = {
|
||||
{"PackedVectorFormat4x8BitKHR", 0, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, 0xffffffffu, 0xffffffffu}
|
||||
{"PackedVectorFormat4x8Bit", 0, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu},
|
||||
{"PackedVectorFormat4x8BitKHR", 0, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_integer_dot_product, {}, SPV_SPIRV_VERSION_WORD(1,6), 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DebugInfoFlagsEntries[] = {
|
||||
|
||||
@@ -517,6 +517,8 @@ typedef enum {
|
||||
|
||||
SPV_ENV_UNIVERSAL_1_5, // SPIR-V 1.5 latest revision, no other restrictions.
|
||||
SPV_ENV_VULKAN_1_2, // Vulkan 1.2 latest revision.
|
||||
|
||||
SPV_ENV_UNIVERSAL_1_6, // SPIR-V 1.6 latest revision, no other restrictions.
|
||||
SPV_ENV_MAX // Keep this as the last enum value.
|
||||
} spv_target_env;
|
||||
|
||||
|
||||
@@ -230,13 +230,14 @@ Optimizer::PassToken CreateNullPass();
|
||||
// Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized.
|
||||
Optimizer::PassToken CreateStripDebugInfoPass();
|
||||
|
||||
// Creates a strip-reflect-info pass.
|
||||
// A strip-reflect-info pass removes all reflections instructions.
|
||||
// For now, this is limited to removing decorations defined in
|
||||
// SPV_GOOGLE_hlsl_functionality1. The coverage may expand in
|
||||
// the future.
|
||||
// [Deprecated] This will create a strip-nonsemantic-info pass. See below.
|
||||
Optimizer::PassToken CreateStripReflectInfoPass();
|
||||
|
||||
// Creates a strip-nonsemantic-info pass.
|
||||
// A strip-nonsemantic-info pass removes all reflections and explicitly
|
||||
// non-semantic instructions.
|
||||
Optimizer::PassToken CreateStripNonSemanticInfoPass();
|
||||
|
||||
// Creates an eliminate-dead-functions pass.
|
||||
// An eliminate-dead-functions pass will remove all functions that are not in
|
||||
// the call trees rooted at entry points and exported functions. These
|
||||
@@ -519,7 +520,8 @@ Optimizer::PassToken CreateDeadInsertElimPass();
|
||||
// interface are considered live and are not eliminated. This mode is needed
|
||||
// by GPU-Assisted validation instrumentation, where a change in the interface
|
||||
// is not allowed.
|
||||
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface = false);
|
||||
Optimizer::PassToken CreateAggressiveDCEPass();
|
||||
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface);
|
||||
|
||||
// Creates a remove-unused-interface-variables pass.
|
||||
// Removes variables referenced on the |OpEntryPoint| instruction that are not
|
||||
|
||||
35
3rdparty/spirv-tools/source/binary.cpp
vendored
35
3rdparty/spirv-tools/source/binary.cpp
vendored
@@ -33,6 +33,7 @@
|
||||
#include "source/operand.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/spirv_endian.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
spv_result_t spvBinaryHeaderGet(const spv_const_binary binary,
|
||||
const spv_endianness_t endian,
|
||||
@@ -62,6 +63,15 @@ spv_result_t spvBinaryHeaderGet(const spv_const_binary binary,
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
std::string spvDecodeLiteralStringOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index) {
|
||||
assert(operand_index < inst.num_operands);
|
||||
const spv_parsed_operand_t& operand = inst.operands[operand_index];
|
||||
|
||||
return spvtools::utils::MakeString(inst.words + operand.offset,
|
||||
operand.num_words);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// A SPIR-V binary parser. A parser instance communicates detailed parse
|
||||
@@ -577,27 +587,18 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
|
||||
convert_operand_endianness = false;
|
||||
const char* string =
|
||||
reinterpret_cast<const char*>(_.words + _.word_index);
|
||||
// Compute the length of the string, but make sure we don't run off the
|
||||
// end of the input.
|
||||
const size_t remaining_input_bytes =
|
||||
sizeof(uint32_t) * (_.num_words - _.word_index);
|
||||
const size_t string_num_content_bytes =
|
||||
spv_strnlen_s(string, remaining_input_bytes);
|
||||
// If there was no terminating null byte, then that's an end-of-input
|
||||
// error.
|
||||
if (string_num_content_bytes == remaining_input_bytes)
|
||||
const size_t max_words = _.num_words - _.word_index;
|
||||
std::string string =
|
||||
spvtools::utils::MakeString(_.words + _.word_index, max_words, false);
|
||||
|
||||
if (string.length() == max_words * 4)
|
||||
return exhaustedInputDiagnostic(inst_offset, opcode, type);
|
||||
// Account for null in the word length, so add 1 for null, then add 3 to
|
||||
// make sure we round up. The following is equivalent to:
|
||||
// (string_num_content_bytes + 1 + 3) / 4
|
||||
const size_t string_num_words = string_num_content_bytes / 4 + 1;
|
||||
|
||||
// Make sure we can record the word count without overflow.
|
||||
//
|
||||
// This error can't currently be triggered because of validity
|
||||
// checks elsewhere.
|
||||
const size_t string_num_words = string.length() / 4 + 1;
|
||||
if (string_num_words > std::numeric_limits<uint16_t>::max()) {
|
||||
return diagnostic() << "Literal string is longer than "
|
||||
<< std::numeric_limits<uint16_t>::max()
|
||||
@@ -611,7 +612,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
// There is only one string literal argument to OpExtInstImport,
|
||||
// so it's sufficient to guard this just on the opcode.
|
||||
const spv_ext_inst_type_t ext_inst_type =
|
||||
spvExtInstImportTypeGet(string);
|
||||
spvExtInstImportTypeGet(string.c_str());
|
||||
if (SPV_EXT_INST_TYPE_NONE == ext_inst_type) {
|
||||
return diagnostic()
|
||||
<< "Invalid extended instruction import '" << string << "'";
|
||||
|
||||
7
3rdparty/spirv-tools/source/binary.h
vendored
7
3rdparty/spirv-tools/source/binary.h
vendored
@@ -15,6 +15,8 @@
|
||||
#ifndef SOURCE_BINARY_H_
|
||||
#define SOURCE_BINARY_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "source/spirv_definition.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
@@ -33,4 +35,9 @@ spv_result_t spvBinaryHeaderGet(const spv_const_binary binary,
|
||||
// replacement for C11's strnlen_s which might not exist in all environments.
|
||||
size_t spv_strnlen_s(const char* str, size_t strsz);
|
||||
|
||||
// Decode the string literal operand with index operand_index from instruction
|
||||
// inst.
|
||||
std::string spvDecodeLiteralStringOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index);
|
||||
|
||||
#endif // SOURCE_BINARY_H_
|
||||
|
||||
700
3rdparty/spirv-tools/source/disassemble.cpp
vendored
700
3rdparty/spirv-tools/source/disassemble.cpp
vendored
@@ -17,6 +17,8 @@
|
||||
// This file contains a disassembler: It converts a SPIR-V binary
|
||||
// to text.
|
||||
|
||||
#include "source/disassemble.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@@ -28,9 +30,7 @@
|
||||
#include "source/assembly_grammar.h"
|
||||
#include "source/binary.h"
|
||||
#include "source/diagnostic.h"
|
||||
#include "source/disassemble.h"
|
||||
#include "source/ext_inst.h"
|
||||
#include "source/name_mapper.h"
|
||||
#include "source/opcode.h"
|
||||
#include "source/parsed_operand.h"
|
||||
#include "source/print.h"
|
||||
@@ -40,29 +40,21 @@
|
||||
#include "source/util/make_unique.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace {
|
||||
|
||||
// A Disassembler instance converts a SPIR-V binary to its assembly
|
||||
// representation.
|
||||
class Disassembler {
|
||||
public:
|
||||
Disassembler(const spvtools::AssemblyGrammar& grammar, uint32_t options,
|
||||
spvtools::NameMapper name_mapper)
|
||||
: grammar_(grammar),
|
||||
print_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options)),
|
||||
color_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COLOR, options)),
|
||||
indent_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_INDENT, options)
|
||||
? kStandardIndent
|
||||
: 0),
|
||||
comment_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COMMENT, options)),
|
||||
Disassembler(const AssemblyGrammar& grammar, uint32_t options,
|
||||
NameMapper name_mapper)
|
||||
: print_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options)),
|
||||
text_(),
|
||||
out_(print_ ? out_stream() : out_stream(text_)),
|
||||
stream_(out_.get()),
|
||||
instruction_disassembler_(grammar, out_.get(), options, name_mapper),
|
||||
header_(!spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER, options)),
|
||||
show_byte_offset_(spvIsInBitfield(
|
||||
SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET, options)),
|
||||
byte_offset_(0),
|
||||
name_mapper_(std::move(name_mapper)) {}
|
||||
byte_offset_(0) {}
|
||||
|
||||
// Emits the assembly header for the module, and sets up internal state
|
||||
// so subsequent callbacks can handle the cases where the entire module
|
||||
@@ -78,56 +70,13 @@ class Disassembler {
|
||||
spv_result_t SaveTextResult(spv_text* text_result) const;
|
||||
|
||||
private:
|
||||
enum { kStandardIndent = 15 };
|
||||
|
||||
using out_stream = spvtools::out_stream;
|
||||
|
||||
// Emits an operand for the given instruction, where the instruction
|
||||
// is at offset words from the start of the binary.
|
||||
void EmitOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index);
|
||||
|
||||
// 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);
|
||||
|
||||
// Resets the output color, if color is turned on.
|
||||
void ResetColor() {
|
||||
if (color_) out_.get() << spvtools::clr::reset{print_};
|
||||
}
|
||||
// Sets the output to grey, if color is turned on.
|
||||
void SetGrey() {
|
||||
if (color_) out_.get() << spvtools::clr::grey{print_};
|
||||
}
|
||||
// Sets the output to blue, if color is turned on.
|
||||
void SetBlue() {
|
||||
if (color_) out_.get() << spvtools::clr::blue{print_};
|
||||
}
|
||||
// Sets the output to yellow, if color is turned on.
|
||||
void SetYellow() {
|
||||
if (color_) out_.get() << spvtools::clr::yellow{print_};
|
||||
}
|
||||
// Sets the output to red, if color is turned on.
|
||||
void SetRed() {
|
||||
if (color_) out_.get() << spvtools::clr::red{print_};
|
||||
}
|
||||
// Sets the output to green, if color is turned on.
|
||||
void SetGreen() {
|
||||
if (color_) out_.get() << spvtools::clr::green{print_};
|
||||
}
|
||||
|
||||
const spvtools::AssemblyGrammar& grammar_;
|
||||
const bool print_; // Should we also print to the standard output stream?
|
||||
const bool color_; // Should we print in colour?
|
||||
const int indent_; // How much to indent. 0 means don't indent
|
||||
const int comment_; // Should we comment the source
|
||||
spv_endianness_t endian_; // The detected endianness of the binary.
|
||||
std::stringstream text_; // Captures the text, if not printing.
|
||||
out_stream out_; // The Output stream. Either to text_ or standard output.
|
||||
std::ostream& stream_; // The output std::stream.
|
||||
const bool header_; // Should we output header as the leading comment?
|
||||
const bool show_byte_offset_; // Should we print byte offset, in hex?
|
||||
size_t byte_offset_; // The number of bytes processed so far.
|
||||
spvtools::NameMapper name_mapper_;
|
||||
disassemble::InstructionDisassembler instruction_disassembler_;
|
||||
const bool header_; // Should we output header as the leading comment?
|
||||
size_t byte_offset_; // The number of bytes processed so far.
|
||||
bool inserted_decoration_space_ = false;
|
||||
bool inserted_debug_space_ = false;
|
||||
bool inserted_type_space_ = false;
|
||||
@@ -139,21 +88,11 @@ spv_result_t Disassembler::HandleHeader(spv_endianness_t endian,
|
||||
endian_ = endian;
|
||||
|
||||
if (header_) {
|
||||
const char* generator_tool =
|
||||
spvGeneratorStr(SPV_GENERATOR_TOOL_PART(generator));
|
||||
stream_ << "; SPIR-V\n"
|
||||
<< "; Version: " << SPV_SPIRV_VERSION_MAJOR_PART(version) << "."
|
||||
<< SPV_SPIRV_VERSION_MINOR_PART(version) << "\n"
|
||||
<< "; Generator: " << generator_tool;
|
||||
// For unknown tools, print the numeric tool value.
|
||||
if (0 == strcmp("Unknown", generator_tool)) {
|
||||
stream_ << "(" << SPV_GENERATOR_TOOL_PART(generator) << ")";
|
||||
}
|
||||
// Print the miscellaneous part of the generator word on the same
|
||||
// line as the tool name.
|
||||
stream_ << "; " << SPV_GENERATOR_MISC_PART(generator) << "\n"
|
||||
<< "; Bound: " << id_bound << "\n"
|
||||
<< "; Schema: " << schema << "\n";
|
||||
instruction_disassembler_.EmitHeaderSpirv();
|
||||
instruction_disassembler_.EmitHeaderVersion(version);
|
||||
instruction_disassembler_.EmitHeaderGenerator(generator);
|
||||
instruction_disassembler_.EmitHeaderIdBound(id_bound);
|
||||
instruction_disassembler_.EmitHeaderSchema(schema);
|
||||
}
|
||||
|
||||
byte_offset_ = SPV_INDEX_INSTRUCTION * sizeof(uint32_t);
|
||||
@@ -163,232 +102,17 @@ spv_result_t Disassembler::HandleHeader(spv_endianness_t endian,
|
||||
|
||||
spv_result_t Disassembler::HandleInstruction(
|
||||
const spv_parsed_instruction_t& inst) {
|
||||
auto opcode = static_cast<SpvOp>(inst.opcode);
|
||||
if (comment_ && opcode == SpvOpFunction) {
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl;
|
||||
}
|
||||
if (comment_ && !inserted_decoration_space_ &&
|
||||
spvOpcodeIsDecoration(opcode)) {
|
||||
inserted_decoration_space_ = true;
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Annotations" << std::endl;
|
||||
}
|
||||
if (comment_ && !inserted_debug_space_ && spvOpcodeIsDebug(opcode)) {
|
||||
inserted_debug_space_ = true;
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Debug Information" << std::endl;
|
||||
}
|
||||
if (comment_ && !inserted_type_space_ && spvOpcodeGeneratesType(opcode)) {
|
||||
inserted_type_space_ = true;
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Types, variables and constants" << std::endl;
|
||||
}
|
||||
instruction_disassembler_.EmitSectionComment(inst, inserted_decoration_space_,
|
||||
inserted_debug_space_,
|
||||
inserted_type_space_);
|
||||
|
||||
if (inst.result_id) {
|
||||
SetBlue();
|
||||
const std::string id_name = name_mapper_(inst.result_id);
|
||||
if (indent_)
|
||||
stream_ << std::setw(std::max(0, indent_ - 3 - int(id_name.size())));
|
||||
stream_ << "%" << id_name;
|
||||
ResetColor();
|
||||
stream_ << " = ";
|
||||
} else {
|
||||
stream_ << std::string(indent_, ' ');
|
||||
}
|
||||
|
||||
stream_ << "Op" << spvOpcodeString(opcode);
|
||||
|
||||
for (uint16_t i = 0; i < inst.num_operands; i++) {
|
||||
const spv_operand_type_t type = inst.operands[i].type;
|
||||
assert(type != SPV_OPERAND_TYPE_NONE);
|
||||
if (type == SPV_OPERAND_TYPE_RESULT_ID) continue;
|
||||
stream_ << " ";
|
||||
EmitOperand(inst, i);
|
||||
}
|
||||
|
||||
if (comment_ && opcode == SpvOpName) {
|
||||
const spv_parsed_operand_t& operand = inst.operands[0];
|
||||
const uint32_t word = inst.words[operand.offset];
|
||||
stream_ << " ; id %" << word;
|
||||
}
|
||||
|
||||
if (show_byte_offset_) {
|
||||
SetGrey();
|
||||
auto saved_flags = stream_.flags();
|
||||
auto saved_fill = stream_.fill();
|
||||
stream_ << " ; 0x" << std::setw(8) << std::hex << std::setfill('0')
|
||||
<< byte_offset_;
|
||||
stream_.flags(saved_flags);
|
||||
stream_.fill(saved_fill);
|
||||
ResetColor();
|
||||
}
|
||||
instruction_disassembler_.EmitInstruction(inst, byte_offset_);
|
||||
|
||||
byte_offset_ += inst.num_words * sizeof(uint32_t);
|
||||
|
||||
stream_ << "\n";
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index) {
|
||||
assert(operand_index < inst.num_operands);
|
||||
const spv_parsed_operand_t& operand = inst.operands[operand_index];
|
||||
const uint32_t word = inst.words[operand.offset];
|
||||
switch (operand.type) {
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
assert(false && "<result-id> is not supposed to be handled here");
|
||||
SetBlue();
|
||||
stream_ << "%" << name_mapper_(word);
|
||||
break;
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
SetYellow();
|
||||
stream_ << "%" << name_mapper_(word);
|
||||
break;
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
||||
spv_ext_inst_desc ext_inst;
|
||||
SetRed();
|
||||
if (grammar_.lookupExtInst(inst.ext_inst_type, word, &ext_inst) ==
|
||||
SPV_SUCCESS) {
|
||||
stream_ << ext_inst->name;
|
||||
} else {
|
||||
if (!spvExtInstIsNonSemantic(inst.ext_inst_type)) {
|
||||
assert(false && "should have caught this earlier");
|
||||
} else {
|
||||
// for non-semantic instruction sets we can just print the number
|
||||
stream_ << word;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (grammar_.lookupOpcode(SpvOp(word), &opcode_desc))
|
||||
assert(false && "should have caught this earlier");
|
||||
SetRed();
|
||||
stream_ << opcode_desc->name;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: {
|
||||
SetRed();
|
||||
spvtools::EmitNumericLiteral(&stream_, inst, operand);
|
||||
ResetColor();
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING: {
|
||||
stream_ << "\"";
|
||||
SetGreen();
|
||||
// Strings are always little-endian, and null-terminated.
|
||||
// Write out the characters, escaping as needed, and without copying
|
||||
// the entire string.
|
||||
auto c_str = reinterpret_cast<const char*>(inst.words + operand.offset);
|
||||
for (auto p = c_str; *p; ++p) {
|
||||
if (*p == '"' || *p == '\\') stream_ << '\\';
|
||||
stream_ << *p;
|
||||
}
|
||||
ResetColor();
|
||||
stream_ << '"';
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
|
||||
case SPV_OPERAND_TYPE_RAY_FLAGS:
|
||||
case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION:
|
||||
case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE:
|
||||
case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE:
|
||||
case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
|
||||
case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_DEBUG_OPERATION:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
|
||||
case SPV_OPERAND_TYPE_FPDENORM_MODE:
|
||||
case SPV_OPERAND_TYPE_FPOPERATION_MODE:
|
||||
case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
|
||||
case SPV_OPERAND_TYPE_OVERFLOW_MODES: {
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(operand.type, word, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
stream_ << entry->name;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
case SPV_OPERAND_TYPE_IMAGE:
|
||||
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
|
||||
EmitMaskOperand(operand.type, word);
|
||||
break;
|
||||
default:
|
||||
if (spvOperandIsConcreteMask(operand.type)) {
|
||||
EmitMaskOperand(operand.type, word);
|
||||
} else if (spvOperandIsConcrete(operand.type)) {
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(operand.type, word, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
stream_ << entry->name;
|
||||
} else {
|
||||
assert(false && "unhandled or invalid case");
|
||||
}
|
||||
break;
|
||||
}
|
||||
ResetColor();
|
||||
}
|
||||
|
||||
void Disassembler::EmitMaskOperand(const spv_operand_type_t type,
|
||||
const uint32_t word) {
|
||||
// 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 '|'.
|
||||
uint32_t remaining_word = word;
|
||||
uint32_t mask;
|
||||
int num_emitted = 0;
|
||||
for (mask = 1; remaining_word; mask <<= 1) {
|
||||
if (remaining_word & mask) {
|
||||
remaining_word ^= mask;
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(type, mask, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
if (num_emitted) stream_ << "|";
|
||||
stream_ << entry->name;
|
||||
num_emitted++;
|
||||
}
|
||||
}
|
||||
if (!num_emitted) {
|
||||
// An operand value of 0 was provided, so represent it by the name
|
||||
// of the 0 value. In many cases, that's "None".
|
||||
spv_operand_desc entry;
|
||||
if (SPV_SUCCESS == grammar_.lookupOperand(type, 0, &entry))
|
||||
stream_ << entry->name;
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t Disassembler::SaveTextResult(spv_text* text_result) const {
|
||||
if (!print_) {
|
||||
size_t length = text_.str().size();
|
||||
@@ -470,8 +194,342 @@ spv_result_t DisassembleTargetInstruction(
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
constexpr int kStandardIndent = 15;
|
||||
} // namespace
|
||||
|
||||
namespace disassemble {
|
||||
InstructionDisassembler::InstructionDisassembler(const AssemblyGrammar& grammar,
|
||||
std::ostream& stream,
|
||||
uint32_t options,
|
||||
NameMapper name_mapper)
|
||||
: grammar_(grammar),
|
||||
stream_(stream),
|
||||
print_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options)),
|
||||
color_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COLOR, options)),
|
||||
indent_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_INDENT, options)
|
||||
? kStandardIndent
|
||||
: 0),
|
||||
comment_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COMMENT, options)),
|
||||
show_byte_offset_(
|
||||
spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET, options)),
|
||||
name_mapper_(std::move(name_mapper)) {}
|
||||
|
||||
void InstructionDisassembler::EmitHeaderSpirv() { stream_ << "; SPIR-V\n"; }
|
||||
|
||||
void InstructionDisassembler::EmitHeaderVersion(uint32_t version) {
|
||||
stream_ << "; Version: " << SPV_SPIRV_VERSION_MAJOR_PART(version) << "."
|
||||
<< SPV_SPIRV_VERSION_MINOR_PART(version) << "\n";
|
||||
}
|
||||
|
||||
void InstructionDisassembler::EmitHeaderGenerator(uint32_t generator) {
|
||||
const char* generator_tool =
|
||||
spvGeneratorStr(SPV_GENERATOR_TOOL_PART(generator));
|
||||
stream_ << "; Generator: " << generator_tool;
|
||||
// For unknown tools, print the numeric tool value.
|
||||
if (0 == strcmp("Unknown", generator_tool)) {
|
||||
stream_ << "(" << SPV_GENERATOR_TOOL_PART(generator) << ")";
|
||||
}
|
||||
// Print the miscellaneous part of the generator word on the same
|
||||
// line as the tool name.
|
||||
stream_ << "; " << SPV_GENERATOR_MISC_PART(generator) << "\n";
|
||||
}
|
||||
|
||||
void InstructionDisassembler::EmitHeaderIdBound(uint32_t id_bound) {
|
||||
stream_ << "; Bound: " << id_bound << "\n";
|
||||
}
|
||||
|
||||
void InstructionDisassembler::EmitHeaderSchema(uint32_t schema) {
|
||||
stream_ << "; Schema: " << schema << "\n";
|
||||
}
|
||||
|
||||
void InstructionDisassembler::EmitInstruction(
|
||||
const spv_parsed_instruction_t& inst, size_t inst_byte_offset) {
|
||||
auto opcode = static_cast<SpvOp>(inst.opcode);
|
||||
|
||||
if (inst.result_id) {
|
||||
SetBlue();
|
||||
const std::string id_name = name_mapper_(inst.result_id);
|
||||
if (indent_)
|
||||
stream_ << std::setw(std::max(0, indent_ - 3 - int(id_name.size())));
|
||||
stream_ << "%" << id_name;
|
||||
ResetColor();
|
||||
stream_ << " = ";
|
||||
} else {
|
||||
stream_ << std::string(indent_, ' ');
|
||||
}
|
||||
|
||||
stream_ << "Op" << spvOpcodeString(opcode);
|
||||
|
||||
for (uint16_t i = 0; i < inst.num_operands; i++) {
|
||||
const spv_operand_type_t type = inst.operands[i].type;
|
||||
assert(type != SPV_OPERAND_TYPE_NONE);
|
||||
if (type == SPV_OPERAND_TYPE_RESULT_ID) continue;
|
||||
stream_ << " ";
|
||||
EmitOperand(inst, i);
|
||||
}
|
||||
|
||||
if (comment_ && opcode == SpvOpName) {
|
||||
const spv_parsed_operand_t& operand = inst.operands[0];
|
||||
const uint32_t word = inst.words[operand.offset];
|
||||
stream_ << " ; id %" << word;
|
||||
}
|
||||
|
||||
if (show_byte_offset_) {
|
||||
SetGrey();
|
||||
auto saved_flags = stream_.flags();
|
||||
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_ << "\n";
|
||||
}
|
||||
|
||||
void InstructionDisassembler::EmitSectionComment(
|
||||
const spv_parsed_instruction_t& inst, bool& inserted_decoration_space,
|
||||
bool& inserted_debug_space, bool& inserted_type_space) {
|
||||
auto opcode = static_cast<SpvOp>(inst.opcode);
|
||||
if (comment_ && opcode == SpvOpFunction) {
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl;
|
||||
}
|
||||
if (comment_ && !inserted_decoration_space && spvOpcodeIsDecoration(opcode)) {
|
||||
inserted_decoration_space = true;
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Annotations" << std::endl;
|
||||
}
|
||||
if (comment_ && !inserted_debug_space && spvOpcodeIsDebug(opcode)) {
|
||||
inserted_debug_space = true;
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Debug Information" << std::endl;
|
||||
}
|
||||
if (comment_ && !inserted_type_space && spvOpcodeGeneratesType(opcode)) {
|
||||
inserted_type_space = true;
|
||||
stream_ << std::endl;
|
||||
stream_ << std::string(indent_, ' ');
|
||||
stream_ << "; Types, variables and constants" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void InstructionDisassembler::EmitOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index) {
|
||||
assert(operand_index < inst.num_operands);
|
||||
const spv_parsed_operand_t& operand = inst.operands[operand_index];
|
||||
const uint32_t word = inst.words[operand.offset];
|
||||
switch (operand.type) {
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
assert(false && "<result-id> is not supposed to be handled here");
|
||||
SetBlue();
|
||||
stream_ << "%" << name_mapper_(word);
|
||||
break;
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
SetYellow();
|
||||
stream_ << "%" << name_mapper_(word);
|
||||
break;
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
||||
spv_ext_inst_desc ext_inst;
|
||||
SetRed();
|
||||
if (grammar_.lookupExtInst(inst.ext_inst_type, word, &ext_inst) ==
|
||||
SPV_SUCCESS) {
|
||||
stream_ << ext_inst->name;
|
||||
} else {
|
||||
if (!spvExtInstIsNonSemantic(inst.ext_inst_type)) {
|
||||
assert(false && "should have caught this earlier");
|
||||
} else {
|
||||
// for non-semantic instruction sets we can just print the number
|
||||
stream_ << word;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (grammar_.lookupOpcode(SpvOp(word), &opcode_desc))
|
||||
assert(false && "should have caught this earlier");
|
||||
SetRed();
|
||||
stream_ << opcode_desc->name;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: {
|
||||
SetRed();
|
||||
EmitNumericLiteral(&stream_, inst, operand);
|
||||
ResetColor();
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING: {
|
||||
stream_ << "\"";
|
||||
SetGreen();
|
||||
|
||||
std::string str = spvDecodeLiteralStringOperand(inst, operand_index);
|
||||
for (char const& c : str) {
|
||||
if (c == '"' || c == '\\') stream_ << '\\';
|
||||
stream_ << c;
|
||||
}
|
||||
ResetColor();
|
||||
stream_ << '"';
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
|
||||
case SPV_OPERAND_TYPE_RAY_FLAGS:
|
||||
case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION:
|
||||
case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE:
|
||||
case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE:
|
||||
case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
|
||||
case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_DEBUG_OPERATION:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
|
||||
case SPV_OPERAND_TYPE_FPDENORM_MODE:
|
||||
case SPV_OPERAND_TYPE_FPOPERATION_MODE:
|
||||
case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
|
||||
case SPV_OPERAND_TYPE_OVERFLOW_MODES: {
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(operand.type, word, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
stream_ << entry->name;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
case SPV_OPERAND_TYPE_IMAGE:
|
||||
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
|
||||
case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
|
||||
EmitMaskOperand(operand.type, word);
|
||||
break;
|
||||
default:
|
||||
if (spvOperandIsConcreteMask(operand.type)) {
|
||||
EmitMaskOperand(operand.type, word);
|
||||
} else if (spvOperandIsConcrete(operand.type)) {
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(operand.type, word, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
stream_ << entry->name;
|
||||
} else {
|
||||
assert(false && "unhandled or invalid case");
|
||||
}
|
||||
break;
|
||||
}
|
||||
ResetColor();
|
||||
}
|
||||
|
||||
void InstructionDisassembler::EmitMaskOperand(const spv_operand_type_t type,
|
||||
const uint32_t word) {
|
||||
// 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 '|'.
|
||||
uint32_t remaining_word = word;
|
||||
uint32_t mask;
|
||||
int num_emitted = 0;
|
||||
for (mask = 1; remaining_word; mask <<= 1) {
|
||||
if (remaining_word & mask) {
|
||||
remaining_word ^= mask;
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(type, mask, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
if (num_emitted) stream_ << "|";
|
||||
stream_ << entry->name;
|
||||
num_emitted++;
|
||||
}
|
||||
}
|
||||
if (!num_emitted) {
|
||||
// An operand value of 0 was provided, so represent it by the name
|
||||
// of the 0 value. In many cases, that's "None".
|
||||
spv_operand_desc entry;
|
||||
if (SPV_SUCCESS == grammar_.lookupOperand(type, 0, &entry))
|
||||
stream_ << entry->name;
|
||||
}
|
||||
}
|
||||
|
||||
void InstructionDisassembler::ResetColor() {
|
||||
if (color_) stream_ << spvtools::clr::reset{print_};
|
||||
}
|
||||
void InstructionDisassembler::SetGrey() {
|
||||
if (color_) stream_ << spvtools::clr::grey{print_};
|
||||
}
|
||||
void InstructionDisassembler::SetBlue() {
|
||||
if (color_) stream_ << spvtools::clr::blue{print_};
|
||||
}
|
||||
void InstructionDisassembler::SetYellow() {
|
||||
if (color_) stream_ << spvtools::clr::yellow{print_};
|
||||
}
|
||||
void InstructionDisassembler::SetRed() {
|
||||
if (color_) stream_ << spvtools::clr::red{print_};
|
||||
}
|
||||
void InstructionDisassembler::SetGreen() {
|
||||
if (color_) stream_ << spvtools::clr::green{print_};
|
||||
}
|
||||
} // namespace disassemble
|
||||
|
||||
std::string spvInstructionBinaryToText(const spv_target_env env,
|
||||
const uint32_t* instCode,
|
||||
const size_t instWordCount,
|
||||
const uint32_t* code,
|
||||
const size_t wordCount,
|
||||
const uint32_t options) {
|
||||
spv_context context = spvContextCreate(env);
|
||||
const AssemblyGrammar grammar(context);
|
||||
if (!grammar.isValid()) {
|
||||
spvContextDestroy(context);
|
||||
return "";
|
||||
}
|
||||
|
||||
// Generate friendly names for Ids if requested.
|
||||
std::unique_ptr<FriendlyNameMapper> friendly_mapper;
|
||||
NameMapper name_mapper = GetTrivialNameMapper();
|
||||
if (options & SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) {
|
||||
friendly_mapper = MakeUnique<FriendlyNameMapper>(context, code, wordCount);
|
||||
name_mapper = friendly_mapper->GetNameMapper();
|
||||
}
|
||||
|
||||
// Now disassemble!
|
||||
Disassembler disassembler(grammar, options, name_mapper);
|
||||
WrappedDisassembler wrapped(&disassembler, instCode, instWordCount);
|
||||
spvBinaryParse(context, &wrapped, code, wordCount, DisassembleTargetHeader,
|
||||
DisassembleTargetInstruction, nullptr);
|
||||
|
||||
spv_text text = nullptr;
|
||||
std::string output;
|
||||
if (disassembler.SaveTextResult(&text) == SPV_SUCCESS) {
|
||||
output.assign(text->str, text->str + text->length);
|
||||
// Drop trailing newline characters.
|
||||
while (!output.empty() && output.back() == '\n') output.pop_back();
|
||||
}
|
||||
spvTextDestroy(text);
|
||||
spvContextDestroy(context);
|
||||
|
||||
return output;
|
||||
}
|
||||
} // namespace spvtools
|
||||
|
||||
spv_result_t spvBinaryToText(const spv_const_context context,
|
||||
const uint32_t* code, const size_t wordCount,
|
||||
const uint32_t options, spv_text* pText,
|
||||
@@ -495,53 +553,13 @@ spv_result_t spvBinaryToText(const spv_const_context context,
|
||||
}
|
||||
|
||||
// Now disassemble!
|
||||
Disassembler disassembler(grammar, options, name_mapper);
|
||||
if (auto error = spvBinaryParse(&hijack_context, &disassembler, code,
|
||||
wordCount, DisassembleHeader,
|
||||
DisassembleInstruction, pDiagnostic)) {
|
||||
spvtools::Disassembler disassembler(grammar, options, name_mapper);
|
||||
if (auto error =
|
||||
spvBinaryParse(&hijack_context, &disassembler, code, wordCount,
|
||||
spvtools::DisassembleHeader,
|
||||
spvtools::DisassembleInstruction, pDiagnostic)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return disassembler.SaveTextResult(pText);
|
||||
}
|
||||
|
||||
std::string spvtools::spvInstructionBinaryToText(const spv_target_env env,
|
||||
const uint32_t* instCode,
|
||||
const size_t instWordCount,
|
||||
const uint32_t* code,
|
||||
const size_t wordCount,
|
||||
const uint32_t options) {
|
||||
spv_context context = spvContextCreate(env);
|
||||
const spvtools::AssemblyGrammar grammar(context);
|
||||
if (!grammar.isValid()) {
|
||||
spvContextDestroy(context);
|
||||
return "";
|
||||
}
|
||||
|
||||
// Generate friendly names for Ids if requested.
|
||||
std::unique_ptr<spvtools::FriendlyNameMapper> friendly_mapper;
|
||||
spvtools::NameMapper name_mapper = spvtools::GetTrivialNameMapper();
|
||||
if (options & SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) {
|
||||
friendly_mapper = spvtools::MakeUnique<spvtools::FriendlyNameMapper>(
|
||||
context, code, wordCount);
|
||||
name_mapper = friendly_mapper->GetNameMapper();
|
||||
}
|
||||
|
||||
// Now disassemble!
|
||||
Disassembler disassembler(grammar, options, name_mapper);
|
||||
WrappedDisassembler wrapped(&disassembler, instCode, instWordCount);
|
||||
spvBinaryParse(context, &wrapped, code, wordCount, DisassembleTargetHeader,
|
||||
DisassembleTargetInstruction, nullptr);
|
||||
|
||||
spv_text text = nullptr;
|
||||
std::string output;
|
||||
if (disassembler.SaveTextResult(&text) == SPV_SUCCESS) {
|
||||
output.assign(text->str, text->str + text->length);
|
||||
// Drop trailing newline characters.
|
||||
while (!output.empty() && output.back() == '\n') output.pop_back();
|
||||
}
|
||||
spvTextDestroy(text);
|
||||
spvContextDestroy(context);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
59
3rdparty/spirv-tools/source/disassemble.h
vendored
59
3rdparty/spirv-tools/source/disassemble.h
vendored
@@ -15,8 +15,10 @@
|
||||
#ifndef SOURCE_DISASSEMBLE_H_
|
||||
#define SOURCE_DISASSEMBLE_H_
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "source/name_mapper.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
@@ -33,6 +35,63 @@ std::string spvInstructionBinaryToText(const spv_target_env env,
|
||||
const size_t word_count,
|
||||
const uint32_t options);
|
||||
|
||||
class AssemblyGrammar;
|
||||
namespace disassemble {
|
||||
|
||||
// Shared code with other tools (than the disassembler) that might need to
|
||||
// output disassembly. An InstructionDisassembler instance converts SPIR-V
|
||||
// binary for an instruction to its assembly representation.
|
||||
class InstructionDisassembler {
|
||||
public:
|
||||
InstructionDisassembler(const AssemblyGrammar& grammar, std::ostream& stream,
|
||||
uint32_t options, NameMapper name_mapper);
|
||||
|
||||
// Emits the assembly header for the module.
|
||||
void EmitHeaderSpirv();
|
||||
void EmitHeaderVersion(uint32_t version);
|
||||
void EmitHeaderGenerator(uint32_t generator);
|
||||
void EmitHeaderIdBound(uint32_t id_bound);
|
||||
void EmitHeaderSchema(uint32_t schema);
|
||||
|
||||
// Emits the assembly text for the given instruction.
|
||||
void EmitInstruction(const spv_parsed_instruction_t& inst,
|
||||
size_t inst_byte_offset);
|
||||
|
||||
// Emits a comment between different sections of the module.
|
||||
void EmitSectionComment(const spv_parsed_instruction_t& inst,
|
||||
bool& inserted_decoration_space,
|
||||
bool& inserted_debug_space,
|
||||
bool& inserted_type_space);
|
||||
|
||||
// Resets the output color, if color is turned on.
|
||||
void ResetColor();
|
||||
// Set the output color, if color is turned on.
|
||||
void SetGrey();
|
||||
void SetBlue();
|
||||
void SetYellow();
|
||||
void SetRed();
|
||||
void SetGreen();
|
||||
|
||||
private:
|
||||
// Emits an operand for the given instruction, where the instruction
|
||||
// is at offset words from the start of the binary.
|
||||
void EmitOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index);
|
||||
|
||||
// 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);
|
||||
|
||||
const spvtools::AssemblyGrammar& grammar_;
|
||||
std::ostream& stream_;
|
||||
const bool print_; // Should we also print to the standard output stream?
|
||||
const bool color_; // Should we print in colour?
|
||||
const int indent_; // How much to indent. 0 means don't indent
|
||||
const int comment_; // Should we comment the source
|
||||
const bool show_byte_offset_; // Should we print byte offset, in hex?
|
||||
spvtools::NameMapper name_mapper_;
|
||||
};
|
||||
|
||||
} // namespace disassemble
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_DISASSEMBLE_H_
|
||||
|
||||
1
3rdparty/spirv-tools/source/ext_inst.cpp
vendored
1
3rdparty/spirv-tools/source/ext_inst.cpp
vendored
@@ -96,6 +96,7 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
|
||||
case SPV_ENV_UNIVERSAL_1_4:
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
*pExtInstTable = &kTable_1_0;
|
||||
return SPV_SUCCESS;
|
||||
default:
|
||||
|
||||
4
3rdparty/spirv-tools/source/extensions.cpp
vendored
4
3rdparty/spirv-tools/source/extensions.cpp
vendored
@@ -18,6 +18,7 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "source/binary.h"
|
||||
#include "source/enum_string_mapping.h"
|
||||
|
||||
namespace spvtools {
|
||||
@@ -30,8 +31,9 @@ std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
|
||||
const auto& operand = inst->operands[0];
|
||||
assert(operand.type == SPV_OPERAND_TYPE_LITERAL_STRING);
|
||||
assert(inst->num_words > operand.offset);
|
||||
(void)operand; /* No unused variables in release builds. */
|
||||
|
||||
return reinterpret_cast<const char*>(inst->words + operand.offset);
|
||||
return spvDecodeLiteralStringOperand(*inst, 0);
|
||||
}
|
||||
|
||||
std::string ExtensionSetToString(const ExtensionSet& extensions) {
|
||||
|
||||
22
3rdparty/spirv-tools/source/link/linker.cpp
vendored
22
3rdparty/spirv-tools/source/link/linker.cpp
vendored
@@ -37,6 +37,7 @@
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/util/make_unique.h"
|
||||
#include "source/util/string_utils.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace spvtools {
|
||||
@@ -210,7 +211,7 @@ spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
header->version = version;
|
||||
header->generator = SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_LINKER, 0);
|
||||
header->bound = max_id_bound;
|
||||
header->reserved = 0u;
|
||||
header->schema = 0u;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
@@ -282,16 +283,15 @@ spv_result_t MergeModules(const MessageConsumer& consumer,
|
||||
memory_model_inst->Clone(linked_context)));
|
||||
} while (false);
|
||||
|
||||
std::vector<std::pair<uint32_t, const char*>> entry_points;
|
||||
std::vector<std::pair<uint32_t, std::string>> entry_points;
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->entry_points()) {
|
||||
const uint32_t model = inst.GetSingleWordInOperand(0);
|
||||
const char* const name =
|
||||
reinterpret_cast<const char*>(inst.GetInOperand(2).words.data());
|
||||
const std::string name = inst.GetInOperand(2).AsString();
|
||||
const auto i = std::find_if(
|
||||
entry_points.begin(), entry_points.end(),
|
||||
[model, name](const std::pair<uint32_t, const char*>& v) {
|
||||
return v.first == model && strcmp(name, v.second) == 0;
|
||||
[model, name](const std::pair<uint32_t, std::string>& v) {
|
||||
return v.first == model && v.second == name;
|
||||
});
|
||||
if (i != entry_points.end()) {
|
||||
spv_operand_desc desc = nullptr;
|
||||
@@ -334,11 +334,8 @@ spv_result_t MergeModules(const MessageConsumer& consumer,
|
||||
// OpModuleProcessed instruction about the linking step.
|
||||
if (linked_module->version() >= 0x10100) {
|
||||
const std::string processed_string("Linked by SPIR-V Tools Linker");
|
||||
const auto num_chars = processed_string.size();
|
||||
// Compute num words, accommodate the terminating null character.
|
||||
const auto num_words = (num_chars + 1 + 3) / 4;
|
||||
std::vector<uint32_t> processed_words(num_words, 0u);
|
||||
std::memcpy(processed_words.data(), processed_string.data(), num_chars);
|
||||
std::vector<uint32_t> processed_words =
|
||||
spvtools::utils::MakeVector(processed_string);
|
||||
linked_module->AddDebug3Inst(std::unique_ptr<Instruction>(
|
||||
new Instruction(linked_context, SpvOpModuleProcessed, 0u, 0u,
|
||||
{{SPV_OPERAND_TYPE_LITERAL_STRING, processed_words}})));
|
||||
@@ -414,8 +411,7 @@ spv_result_t GetImportExportPairs(const MessageConsumer& consumer,
|
||||
const uint32_t type = decoration.GetSingleWordInOperand(3u);
|
||||
|
||||
LinkageSymbolInfo symbol_info;
|
||||
symbol_info.name =
|
||||
reinterpret_cast<const char*>(decoration.GetInOperand(2u).words.data());
|
||||
symbol_info.name = decoration.GetInOperand(2u).AsString();
|
||||
symbol_info.id = id;
|
||||
symbol_info.type_id = 0u;
|
||||
|
||||
|
||||
11
3rdparty/spirv-tools/source/name_mapper.cpp
vendored
11
3rdparty/spirv-tools/source/name_mapper.cpp
vendored
@@ -22,10 +22,10 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
#include "source/binary.h"
|
||||
#include "source/latest_version_spirv_header.h"
|
||||
#include "source/parsed_operand.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace {
|
||||
@@ -172,7 +172,7 @@ spv_result_t FriendlyNameMapper::ParseInstruction(
|
||||
const auto result_id = inst.result_id;
|
||||
switch (inst.opcode) {
|
||||
case SpvOpName:
|
||||
SaveName(inst.words[1], reinterpret_cast<const char*>(inst.words + 2));
|
||||
SaveName(inst.words[1], spvDecodeLiteralStringOperand(inst, 1));
|
||||
break;
|
||||
case SpvOpDecorate:
|
||||
// Decorations come after OpName. So OpName will take precedence over
|
||||
@@ -274,9 +274,8 @@ spv_result_t FriendlyNameMapper::ParseInstruction(
|
||||
SaveName(result_id, "Queue");
|
||||
break;
|
||||
case SpvOpTypeOpaque:
|
||||
SaveName(result_id,
|
||||
std::string("Opaque_") +
|
||||
Sanitize(reinterpret_cast<const char*>(inst.words + 2)));
|
||||
SaveName(result_id, std::string("Opaque_") +
|
||||
Sanitize(spvDecodeLiteralStringOperand(inst, 1)));
|
||||
break;
|
||||
case SpvOpTypePipeStorage:
|
||||
SaveName(result_id, "PipeStorage");
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "source/opt/iterator.h"
|
||||
#include "source/opt/reflect.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -146,8 +147,7 @@ void AggressiveDCEPass::AddStores(Function* func, uint32_t ptrId) {
|
||||
bool AggressiveDCEPass::AllExtensionsSupported() const {
|
||||
// If any extension not in allowlist, return false
|
||||
for (auto& ei : get_module()->extensions()) {
|
||||
const char* extName =
|
||||
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
|
||||
const std::string extName = ei.GetInOperand(0).AsString();
|
||||
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
|
||||
return false;
|
||||
}
|
||||
@@ -156,11 +156,9 @@ bool AggressiveDCEPass::AllExtensionsSupported() const {
|
||||
for (auto& inst : context()->module()->ext_inst_imports()) {
|
||||
assert(inst.opcode() == SpvOpExtInstImport &&
|
||||
"Expecting an import of an extension's instruction set.");
|
||||
const char* extension_name =
|
||||
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
|
||||
if (0 == std::strncmp(extension_name, "NonSemantic.", 12) &&
|
||||
0 != std::strncmp(extension_name, "NonSemantic.Shader.DebugInfo.100",
|
||||
32)) {
|
||||
const std::string extension_name = inst.GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
|
||||
extension_name != "NonSemantic.Shader.DebugInfo.100") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,8 +935,7 @@ Pass::Status AmdExtensionToKhrPass::Process() {
|
||||
std::vector<Instruction*> to_be_killed;
|
||||
for (Instruction& inst : context()->module()->extensions()) {
|
||||
if (inst.opcode() == SpvOpExtension) {
|
||||
if (ext_to_remove.count(reinterpret_cast<const char*>(
|
||||
&(inst.GetInOperand(0).words[0]))) != 0) {
|
||||
if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
|
||||
to_be_killed.push_back(&inst);
|
||||
}
|
||||
}
|
||||
@@ -944,8 +943,7 @@ Pass::Status AmdExtensionToKhrPass::Process() {
|
||||
|
||||
for (Instruction& inst : context()->ext_inst_imports()) {
|
||||
if (inst.opcode() == SpvOpExtInstImport) {
|
||||
if (ext_to_remove.count(reinterpret_cast<const char*>(
|
||||
&(inst.GetInOperand(0).words[0]))) != 0) {
|
||||
if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
|
||||
to_be_killed.push_back(&inst);
|
||||
}
|
||||
}
|
||||
|
||||
43
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
43
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
@@ -102,6 +102,34 @@ SSAPropagator::PropStatus CCPPass::VisitPhi(Instruction* phi) {
|
||||
return SSAPropagator::kInteresting;
|
||||
}
|
||||
|
||||
uint32_t CCPPass::ComputeLatticeMeet(Instruction* instr, uint32_t val2) {
|
||||
// Given two values val1 and val2, the meet operation in the constant
|
||||
// lattice uses the following rules:
|
||||
//
|
||||
// meet(val1, UNDEFINED) = val1
|
||||
// meet(val1, VARYING) = VARYING
|
||||
// meet(val1, val2) = val1 if val1 == val2
|
||||
// meet(val1, val2) = VARYING if val1 != val2
|
||||
//
|
||||
// When two different values meet, the result is always varying because CCP
|
||||
// does not allow lateral transitions in the lattice. This prevents
|
||||
// infinite cycles during propagation.
|
||||
auto val1_it = values_.find(instr->result_id());
|
||||
if (val1_it == values_.end()) {
|
||||
return val2;
|
||||
}
|
||||
|
||||
uint32_t val1 = val1_it->second;
|
||||
if (IsVaryingValue(val1)) {
|
||||
return val1;
|
||||
} else if (IsVaryingValue(val2)) {
|
||||
return val2;
|
||||
} else if (val1 != val2) {
|
||||
return kVaryingSSAId;
|
||||
}
|
||||
return val2;
|
||||
}
|
||||
|
||||
SSAPropagator::PropStatus CCPPass::VisitAssignment(Instruction* instr) {
|
||||
assert(instr->result_id() != 0 &&
|
||||
"Expecting an instruction that produces a result");
|
||||
@@ -115,8 +143,10 @@ SSAPropagator::PropStatus CCPPass::VisitAssignment(Instruction* instr) {
|
||||
if (IsVaryingValue(it->second)) {
|
||||
return MarkInstructionVarying(instr);
|
||||
} else {
|
||||
values_[instr->result_id()] = it->second;
|
||||
return SSAPropagator::kInteresting;
|
||||
uint32_t new_val = ComputeLatticeMeet(instr, it->second);
|
||||
values_[instr->result_id()] = new_val;
|
||||
return IsVaryingValue(new_val) ? SSAPropagator::kVarying
|
||||
: SSAPropagator::kInteresting;
|
||||
}
|
||||
}
|
||||
return SSAPropagator::kNotInteresting;
|
||||
@@ -142,9 +172,12 @@ SSAPropagator::PropStatus CCPPass::VisitAssignment(Instruction* instr) {
|
||||
if (folded_inst != nullptr) {
|
||||
// We do not want to change the body of the function by adding new
|
||||
// instructions. When folding we can only generate new constants.
|
||||
assert(folded_inst->IsConstant() && "CCP is only interested in constant.");
|
||||
values_[instr->result_id()] = folded_inst->result_id();
|
||||
return SSAPropagator::kInteresting;
|
||||
assert(folded_inst->IsConstant() &&
|
||||
"CCP is only interested in constant values.");
|
||||
uint32_t new_val = ComputeLatticeMeet(instr, folded_inst->result_id());
|
||||
values_[instr->result_id()] = new_val;
|
||||
return IsVaryingValue(new_val) ? SSAPropagator::kVarying
|
||||
: SSAPropagator::kInteresting;
|
||||
}
|
||||
|
||||
// Conservatively mark this instruction as varying if any input id is varying.
|
||||
|
||||
16
3rdparty/spirv-tools/source/opt/ccp_pass.h
vendored
16
3rdparty/spirv-tools/source/opt/ccp_pass.h
vendored
@@ -92,6 +92,22 @@ class CCPPass : public MemPass {
|
||||
// generated during propagation.
|
||||
analysis::ConstantManager* const_mgr_;
|
||||
|
||||
// Returns a new value for |instr| by computing the meet operation between
|
||||
// its existing value and |val2|.
|
||||
//
|
||||
// Given two values val1 and val2, the meet operation in the constant
|
||||
// lattice uses the following rules:
|
||||
//
|
||||
// meet(val1, UNDEFINED) = val1
|
||||
// meet(val1, VARYING) = VARYING
|
||||
// meet(val1, val2) = val1 if val1 == val2
|
||||
// meet(val1, val2) = VARYING if val1 != val2
|
||||
//
|
||||
// When two different values meet, the result is always varying because CCP
|
||||
// does not allow lateral transitions in the lattice. This prevents
|
||||
// infinite cycles during propagation.
|
||||
uint32_t ComputeLatticeMeet(Instruction* instr, uint32_t val2);
|
||||
|
||||
// Constant value table. Each entry <id, const_decl_id> in this map
|
||||
// represents the compile-time constant value for |id| as declared by
|
||||
// |const_decl_id|. Each |const_decl_id| in this table is an OpConstant
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
|
||||
#include "source/opt/def_use_manager.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "source/opt/log.h"
|
||||
#include "source/opt/reflect.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
namespace analysis {
|
||||
@@ -58,8 +53,8 @@ void DefUseManager::AnalyzeInstUse(Instruction* inst) {
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID: {
|
||||
uint32_t use_id = inst->GetSingleWordOperand(i);
|
||||
Instruction* def = GetDef(use_id);
|
||||
if (!def) assert(false && "Definition is not registered.");
|
||||
id_to_users_.insert(UserEntry(def, inst));
|
||||
assert(def && "Definition is not registered.");
|
||||
id_to_users_.insert(UserEntry{def, inst});
|
||||
used_ids->push_back(use_id);
|
||||
} break;
|
||||
default:
|
||||
@@ -102,13 +97,13 @@ const Instruction* DefUseManager::GetDef(uint32_t id) const {
|
||||
DefUseManager::IdToUsersMap::const_iterator DefUseManager::UsersBegin(
|
||||
const Instruction* def) const {
|
||||
return id_to_users_.lower_bound(
|
||||
UserEntry(const_cast<Instruction*>(def), nullptr));
|
||||
UserEntry{const_cast<Instruction*>(def), nullptr});
|
||||
}
|
||||
|
||||
bool DefUseManager::UsersNotEnd(const IdToUsersMap::const_iterator& iter,
|
||||
const IdToUsersMap::const_iterator& cached_end,
|
||||
const Instruction* inst) const {
|
||||
return (iter != cached_end && iter->first == inst);
|
||||
return (iter != cached_end && iter->def == inst);
|
||||
}
|
||||
|
||||
bool DefUseManager::UsersNotEnd(const IdToUsersMap::const_iterator& iter,
|
||||
@@ -125,7 +120,7 @@ bool DefUseManager::WhileEachUser(
|
||||
|
||||
auto end = id_to_users_.end();
|
||||
for (auto iter = UsersBegin(def); UsersNotEnd(iter, end, def); ++iter) {
|
||||
if (!f(iter->second)) return false;
|
||||
if (!f(iter->user)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -158,7 +153,7 @@ bool DefUseManager::WhileEachUse(
|
||||
|
||||
auto end = id_to_users_.end();
|
||||
for (auto iter = UsersBegin(def); UsersNotEnd(iter, end, def); ++iter) {
|
||||
Instruction* user = iter->second;
|
||||
Instruction* user = iter->user;
|
||||
for (uint32_t idx = 0; idx != user->NumOperands(); ++idx) {
|
||||
const Operand& op = user->GetOperand(idx);
|
||||
if (op.type != SPV_OPERAND_TYPE_RESULT_ID && spvIsIdType(op.type)) {
|
||||
@@ -258,55 +253,59 @@ void DefUseManager::EraseUseRecordsOfOperandIds(const Instruction* inst) {
|
||||
if (iter != inst_to_used_ids_.end()) {
|
||||
for (auto use_id : iter->second) {
|
||||
id_to_users_.erase(
|
||||
UserEntry(GetDef(use_id), const_cast<Instruction*>(inst)));
|
||||
UserEntry{GetDef(use_id), const_cast<Instruction*>(inst)});
|
||||
}
|
||||
inst_to_used_ids_.erase(inst);
|
||||
inst_to_used_ids_.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const DefUseManager& lhs, const DefUseManager& rhs) {
|
||||
bool CompareAndPrintDifferences(const DefUseManager& lhs,
|
||||
const DefUseManager& rhs) {
|
||||
bool same = true;
|
||||
|
||||
if (lhs.id_to_def_ != rhs.id_to_def_) {
|
||||
for (auto p : lhs.id_to_def_) {
|
||||
if (rhs.id_to_def_.find(p.first) == rhs.id_to_def_.end()) {
|
||||
return false;
|
||||
printf("Diff in id_to_def: missing value in rhs\n");
|
||||
}
|
||||
}
|
||||
for (auto p : rhs.id_to_def_) {
|
||||
if (lhs.id_to_def_.find(p.first) == lhs.id_to_def_.end()) {
|
||||
return false;
|
||||
printf("Diff in id_to_def: missing value in lhs\n");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
same = false;
|
||||
}
|
||||
|
||||
if (lhs.id_to_users_ != rhs.id_to_users_) {
|
||||
for (auto p : lhs.id_to_users_) {
|
||||
if (rhs.id_to_users_.count(p) == 0) {
|
||||
return false;
|
||||
printf("Diff in id_to_users: missing value in rhs\n");
|
||||
}
|
||||
}
|
||||
for (auto p : rhs.id_to_users_) {
|
||||
if (lhs.id_to_users_.count(p) == 0) {
|
||||
return false;
|
||||
printf("Diff in id_to_users: missing value in lhs\n");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
same = false;
|
||||
}
|
||||
|
||||
if (lhs.inst_to_used_ids_ != rhs.inst_to_used_ids_) {
|
||||
for (auto p : lhs.inst_to_used_ids_) {
|
||||
if (rhs.inst_to_used_ids_.count(p.first) == 0) {
|
||||
return false;
|
||||
printf("Diff in inst_to_used_ids: missing value in rhs\n");
|
||||
}
|
||||
}
|
||||
for (auto p : rhs.inst_to_used_ids_) {
|
||||
if (lhs.inst_to_used_ids_.count(p.first) == 0) {
|
||||
return false;
|
||||
printf("Diff in inst_to_used_ids: missing value in lhs\n");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
same = false;
|
||||
}
|
||||
return true;
|
||||
|
||||
return same;
|
||||
}
|
||||
|
||||
} // namespace analysis
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#ifndef SOURCE_OPT_DEF_USE_MANAGER_H_
|
||||
#define SOURCE_OPT_DEF_USE_MANAGER_H_
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "source/opt/instruction.h"
|
||||
@@ -51,15 +49,17 @@ inline bool operator<(const Use& lhs, const Use& rhs) {
|
||||
return lhs.operand_index < rhs.operand_index;
|
||||
}
|
||||
|
||||
// Definition and user pair.
|
||||
//
|
||||
// The first element of the pair is the definition.
|
||||
// The second element of the pair is the user.
|
||||
//
|
||||
// Definition should never be null. User can be null, however, such an entry
|
||||
// should be used only for searching (e.g. all users of a particular definition)
|
||||
// and never stored in a container.
|
||||
using UserEntry = std::pair<Instruction*, Instruction*>;
|
||||
struct UserEntry {
|
||||
Instruction* def;
|
||||
Instruction* user;
|
||||
};
|
||||
|
||||
inline bool operator==(const UserEntry& lhs, const UserEntry& rhs) {
|
||||
return lhs.def == rhs.def && lhs.user == rhs.user;
|
||||
}
|
||||
|
||||
// Orders UserEntry for use in associative containers (i.e. less than ordering).
|
||||
//
|
||||
@@ -72,24 +72,24 @@ using UserEntry = std::pair<Instruction*, Instruction*>;
|
||||
// definition (i.e. using {def, nullptr}).
|
||||
struct UserEntryLess {
|
||||
bool operator()(const UserEntry& lhs, const UserEntry& rhs) const {
|
||||
// If lhs.first and rhs.first are both null, fall through to checking the
|
||||
// If lhs.def and rhs.def are both null, fall through to checking the
|
||||
// second entries.
|
||||
if (!lhs.first && rhs.first) return true;
|
||||
if (lhs.first && !rhs.first) return false;
|
||||
if (!lhs.def && rhs.def) return true;
|
||||
if (lhs.def && !rhs.def) return false;
|
||||
|
||||
// If neither definition is null, then compare unique ids.
|
||||
if (lhs.first && rhs.first) {
|
||||
if (lhs.first->unique_id() < rhs.first->unique_id()) return true;
|
||||
if (rhs.first->unique_id() < lhs.first->unique_id()) return false;
|
||||
if (lhs.def && rhs.def) {
|
||||
if (lhs.def->unique_id() < rhs.def->unique_id()) return true;
|
||||
if (rhs.def->unique_id() < lhs.def->unique_id()) return false;
|
||||
}
|
||||
|
||||
// Return false on equality.
|
||||
if (!lhs.second && !rhs.second) return false;
|
||||
if (!lhs.second) return true;
|
||||
if (!rhs.second) return false;
|
||||
if (!lhs.user && !rhs.user) return false;
|
||||
if (!lhs.user) return true;
|
||||
if (!rhs.user) return false;
|
||||
|
||||
// If neither user is null then compare unique ids.
|
||||
return lhs.second->unique_id() < rhs.second->unique_id();
|
||||
return lhs.user->unique_id() < rhs.user->unique_id();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -97,7 +97,6 @@ struct UserEntryLess {
|
||||
class DefUseManager {
|
||||
public:
|
||||
using IdToDefMap = std::unordered_map<uint32_t, Instruction*>;
|
||||
using IdToUsersMap = std::set<UserEntry, UserEntryLess>;
|
||||
|
||||
// Constructs a def-use manager from the given |module|. All internal messages
|
||||
// will be communicated to the outside via the given message |consumer|. This
|
||||
@@ -197,8 +196,6 @@ class DefUseManager {
|
||||
|
||||
// Returns the map from ids to their def instructions.
|
||||
const IdToDefMap& id_to_defs() const { return id_to_def_; }
|
||||
// Returns the map from instructions to their users.
|
||||
const IdToUsersMap& id_to_users() const { return id_to_users_; }
|
||||
|
||||
// Clear the internal def-use record of the given instruction |inst|. This
|
||||
// method will update the use information of the operand ids of |inst|. The
|
||||
@@ -210,16 +207,15 @@ class DefUseManager {
|
||||
// Erases the records that a given instruction uses its operand ids.
|
||||
void EraseUseRecordsOfOperandIds(const Instruction* inst);
|
||||
|
||||
friend bool operator==(const DefUseManager&, const DefUseManager&);
|
||||
friend bool operator!=(const DefUseManager& lhs, const DefUseManager& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
friend bool CompareAndPrintDifferences(const DefUseManager&,
|
||||
const DefUseManager&);
|
||||
|
||||
// If |inst| has not already been analysed, then analyses its defintion and
|
||||
// uses.
|
||||
void UpdateDefUse(Instruction* inst);
|
||||
|
||||
private:
|
||||
using IdToUsersMap = std::set<UserEntry, UserEntryLess>;
|
||||
using InstToUsedIdsMap =
|
||||
std::unordered_map<const Instruction*, std::vector<uint32_t>>;
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ void DescriptorScalarReplacement::CopyDecorationsForNewVariable(
|
||||
Instruction* old_var, uint32_t index, uint32_t new_var_id,
|
||||
uint32_t new_var_ptr_type_id, const bool is_old_var_array,
|
||||
const bool is_old_var_struct, Instruction* old_var_type) {
|
||||
// Handle OpDecorate instructions.
|
||||
// Handle OpDecorate and OpDecorateString instructions.
|
||||
for (auto old_decoration :
|
||||
get_decoration_mgr()->GetDecorationsFor(old_var->result_id(), true)) {
|
||||
uint32_t new_binding = 0;
|
||||
@@ -212,7 +212,8 @@ uint32_t DescriptorScalarReplacement::GetNewBindingForElement(
|
||||
|
||||
void DescriptorScalarReplacement::CreateNewDecorationForNewVariable(
|
||||
Instruction* old_decoration, uint32_t new_var_id, uint32_t new_binding) {
|
||||
assert(old_decoration->opcode() == SpvOpDecorate);
|
||||
assert(old_decoration->opcode() == SpvOpDecorate ||
|
||||
old_decoration->opcode() == SpvOpDecorateString);
|
||||
std::unique_ptr<Instruction> new_decoration(old_decoration->Clone(context()));
|
||||
new_decoration->SetInOperand(0, {new_var_id});
|
||||
|
||||
|
||||
9
3rdparty/spirv-tools/source/opt/desc_sroa.h
vendored
9
3rdparty/spirv-tools/source/opt/desc_sroa.h
vendored
@@ -115,10 +115,11 @@ class DescriptorScalarReplacement : public Pass {
|
||||
const bool is_old_var_struct,
|
||||
Instruction* old_var_type);
|
||||
|
||||
// Create a new OpDecorate instruction by cloning |old_decoration|. The new
|
||||
// OpDecorate instruction will be used for a variable whose id is
|
||||
// |new_var_ptr_type_id|. If |old_decoration| is a decoration for a binding,
|
||||
// the new OpDecorate instruction will have |new_binding| as its binding.
|
||||
// Create a new OpDecorate(String) instruction by cloning |old_decoration|.
|
||||
// The new OpDecorate(String) instruction will be used for a variable whose id
|
||||
// is |new_var_ptr_type_id|. If |old_decoration| is a decoration for a
|
||||
// binding, the new OpDecorate(String) instruction will have |new_binding| as
|
||||
// its binding.
|
||||
void CreateNewDecorationForNewVariable(Instruction* old_decoration,
|
||||
uint32_t new_var_id,
|
||||
uint32_t new_binding);
|
||||
|
||||
@@ -39,8 +39,7 @@ void FeatureManager::AddExtension(Instruction* ext) {
|
||||
assert(ext->opcode() == SpvOpExtension &&
|
||||
"Expecting an extension instruction.");
|
||||
|
||||
const std::string name =
|
||||
reinterpret_cast<const char*>(ext->GetInOperand(0u).words.data());
|
||||
const std::string name = ext->GetInOperand(0u).AsString();
|
||||
Extension extension;
|
||||
if (GetExtensionFromString(name.c_str(), &extension)) {
|
||||
extensions_.Add(extension);
|
||||
|
||||
@@ -559,21 +559,17 @@ uint32_t GraphicsRobustAccessPass::GetGlslInsts() {
|
||||
if (module_status_.glsl_insts_id == 0) {
|
||||
// This string serves double-duty as raw data for a string and for a vector
|
||||
// of 32-bit words
|
||||
const char glsl[] = "GLSL.std.450\0\0\0\0";
|
||||
const size_t glsl_str_byte_len = 16;
|
||||
const char glsl[] = "GLSL.std.450";
|
||||
// Use an existing import if we can.
|
||||
for (auto& inst : context()->module()->ext_inst_imports()) {
|
||||
const auto& name_words = inst.GetInOperand(0).words;
|
||||
if (0 == std::strncmp(reinterpret_cast<const char*>(name_words.data()),
|
||||
glsl, glsl_str_byte_len)) {
|
||||
if (inst.GetInOperand(0).AsString() == glsl) {
|
||||
module_status_.glsl_insts_id = inst.result_id();
|
||||
}
|
||||
}
|
||||
if (module_status_.glsl_insts_id == 0) {
|
||||
// Make a new import instruction.
|
||||
module_status_.glsl_insts_id = TakeNextId();
|
||||
std::vector<uint32_t> words(glsl_str_byte_len / sizeof(uint32_t));
|
||||
std::memcpy(words.data(), glsl, glsl_str_byte_len);
|
||||
std::vector<uint32_t> words = spvtools::utils::MakeVector(glsl);
|
||||
auto import_inst = MakeUnique<Instruction>(
|
||||
context(), SpvOpExtInstImport, 0, module_status_.glsl_insts_id,
|
||||
std::initializer_list<Operand>{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "inst_debug_printf_pass.h"
|
||||
|
||||
#include "source/util/string_utils.h"
|
||||
#include "spirv/unified1/NonSemanticDebugPrintf.h"
|
||||
|
||||
namespace spvtools {
|
||||
@@ -231,10 +232,8 @@ Pass::Status InstDebugPrintfPass::ProcessImpl() {
|
||||
bool non_sem_set_seen = false;
|
||||
for (auto c_itr = context()->module()->ext_inst_import_begin();
|
||||
c_itr != context()->module()->ext_inst_import_end(); ++c_itr) {
|
||||
const char* set_name =
|
||||
reinterpret_cast<const char*>(&c_itr->GetInOperand(0).words[0]);
|
||||
const char* non_sem_str = "NonSemantic.";
|
||||
if (!strncmp(set_name, non_sem_str, strlen(non_sem_str))) {
|
||||
const std::string set_name = c_itr->GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(set_name, "NonSemantic.")) {
|
||||
non_sem_set_seen = true;
|
||||
break;
|
||||
}
|
||||
@@ -242,9 +241,8 @@ Pass::Status InstDebugPrintfPass::ProcessImpl() {
|
||||
if (!non_sem_set_seen) {
|
||||
for (auto c_itr = context()->module()->extension_begin();
|
||||
c_itr != context()->module()->extension_end(); ++c_itr) {
|
||||
const char* ext_name =
|
||||
reinterpret_cast<const char*>(&c_itr->GetInOperand(0).words[0]);
|
||||
if (!strcmp(ext_name, "SPV_KHR_non_semantic_info")) {
|
||||
const std::string ext_name = c_itr->GetInOperand(0).AsString();
|
||||
if (ext_name == "SPV_KHR_non_semantic_info") {
|
||||
context()->KillInst(&*c_itr);
|
||||
break;
|
||||
}
|
||||
|
||||
13
3rdparty/spirv-tools/source/opt/instruction.h
vendored
13
3rdparty/spirv-tools/source/opt/instruction.h
vendored
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "NonSemanticShaderDebugInfo100.h"
|
||||
#include "OpenCLDebugInfo100.h"
|
||||
#include "source/binary.h"
|
||||
#include "source/common_debug_info.h"
|
||||
#include "source/latest_version_glsl_std_450_header.h"
|
||||
#include "source/latest_version_spirv_header.h"
|
||||
@@ -32,6 +33,7 @@
|
||||
#include "source/opt/reflect.h"
|
||||
#include "source/util/ilist_node.h"
|
||||
#include "source/util/small_vector.h"
|
||||
#include "source/util/string_utils.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
const uint32_t kNoDebugScope = 0;
|
||||
@@ -85,14 +87,11 @@ struct Operand {
|
||||
spv_operand_type_t type; // Type of this logical operand.
|
||||
OperandData words; // Binary segments of this logical operand.
|
||||
|
||||
// Returns a string operand as a C-style string.
|
||||
const char* AsCString() const {
|
||||
assert(type == SPV_OPERAND_TYPE_LITERAL_STRING);
|
||||
return reinterpret_cast<const char*>(words.data());
|
||||
}
|
||||
|
||||
// Returns a string operand as a std::string.
|
||||
std::string AsString() const { return AsCString(); }
|
||||
std::string AsString() const {
|
||||
assert(type == SPV_OPERAND_TYPE_LITERAL_STRING);
|
||||
return spvtools::utils::MakeString(words);
|
||||
}
|
||||
|
||||
// Returns a literal integer operand as a uint64_t
|
||||
uint64_t AsLiteralUint64() const {
|
||||
|
||||
13
3rdparty/spirv-tools/source/opt/ir_context.cpp
vendored
13
3rdparty/spirv-tools/source/opt/ir_context.cpp
vendored
@@ -317,7 +317,7 @@ bool IRContext::IsConsistent() {
|
||||
#else
|
||||
if (AreAnalysesValid(kAnalysisDefUse)) {
|
||||
analysis::DefUseManager new_def_use(module());
|
||||
if (*get_def_use_mgr() != new_def_use) {
|
||||
if (!CompareAndPrintDifferences(*get_def_use_mgr(), new_def_use)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -623,9 +623,8 @@ void IRContext::AddCombinatorsForCapability(uint32_t capability) {
|
||||
void IRContext::AddCombinatorsForExtension(Instruction* extension) {
|
||||
assert(extension->opcode() == SpvOpExtInstImport &&
|
||||
"Expecting an import of an extension's instruction set.");
|
||||
const char* extension_name =
|
||||
reinterpret_cast<const char*>(&extension->GetInOperand(0).words[0]);
|
||||
if (!strcmp(extension_name, "GLSL.std.450")) {
|
||||
const std::string extension_name = extension->GetInOperand(0).AsString();
|
||||
if (extension_name == "GLSL.std.450") {
|
||||
combinator_ops_[extension->result_id()] = {GLSLstd450Round,
|
||||
GLSLstd450RoundEven,
|
||||
GLSLstd450Trunc,
|
||||
@@ -944,11 +943,11 @@ void IRContext::EmitErrorMessage(std::string message, Instruction* inst) {
|
||||
|
||||
uint32_t line_number = 0;
|
||||
uint32_t col_number = 0;
|
||||
char* source = nullptr;
|
||||
std::string source;
|
||||
if (line_inst != nullptr) {
|
||||
Instruction* file_name =
|
||||
get_def_use_mgr()->GetDef(line_inst->GetSingleWordInOperand(0));
|
||||
source = reinterpret_cast<char*>(&file_name->GetInOperand(0).words[0]);
|
||||
source = file_name->GetInOperand(0).AsString();
|
||||
|
||||
// Get the line number and column number.
|
||||
line_number = line_inst->GetSingleWordInOperand(1);
|
||||
@@ -957,7 +956,7 @@ void IRContext::EmitErrorMessage(std::string message, Instruction* inst) {
|
||||
|
||||
message +=
|
||||
"\n " + inst->PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
|
||||
consumer()(SPV_MSG_ERROR, source, {line_number, col_number, 0},
|
||||
consumer()(SPV_MSG_ERROR, source.c_str(), {line_number, col_number, 0},
|
||||
message.c_str());
|
||||
}
|
||||
|
||||
|
||||
25
3rdparty/spirv-tools/source/opt/ir_context.h
vendored
25
3rdparty/spirv-tools/source/opt/ir_context.h
vendored
@@ -43,6 +43,7 @@
|
||||
#include "source/opt/type_manager.h"
|
||||
#include "source/opt/value_number_table.h"
|
||||
#include "source/util/make_unique.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -518,6 +519,18 @@ class IRContext {
|
||||
std::string message = "ID overflow. Try running compact-ids.";
|
||||
consumer()(SPV_MSG_ERROR, "", {0, 0, 0}, message.c_str());
|
||||
}
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
// If TakeNextId returns 0, it is very likely that execution will
|
||||
// subsequently fail. Such failures are false alarms from a fuzzing point
|
||||
// of view: they are due to the fact that too many ids were used, rather
|
||||
// than being due to an actual bug. Thus, during a fuzzing build, it is
|
||||
// preferable to bail out when ID overflow occurs.
|
||||
//
|
||||
// A zero exit code is returned here because a non-zero code would cause
|
||||
// ClusterFuzz/OSS-Fuzz to regard the termination as a crash, and spurious
|
||||
// crash reports is what this guard aims to avoid.
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
return next_id;
|
||||
}
|
||||
@@ -1020,11 +1033,7 @@ void IRContext::AddCapability(std::unique_ptr<Instruction>&& c) {
|
||||
}
|
||||
|
||||
void IRContext::AddExtension(const std::string& ext_name) {
|
||||
const auto num_chars = ext_name.size();
|
||||
// Compute num words, accommodate the terminating null character.
|
||||
const auto num_words = (num_chars + 1 + 3) / 4;
|
||||
std::vector<uint32_t> ext_words(num_words, 0u);
|
||||
std::memcpy(ext_words.data(), ext_name.data(), num_chars);
|
||||
std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(ext_name);
|
||||
AddExtension(std::unique_ptr<Instruction>(
|
||||
new Instruction(this, SpvOpExtension, 0u, 0u,
|
||||
{{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
|
||||
@@ -1041,11 +1050,7 @@ void IRContext::AddExtension(std::unique_ptr<Instruction>&& e) {
|
||||
}
|
||||
|
||||
void IRContext::AddExtInstImport(const std::string& name) {
|
||||
const auto num_chars = name.size();
|
||||
// Compute num words, accommodate the terminating null character.
|
||||
const auto num_words = (num_chars + 1 + 3) / 4;
|
||||
std::vector<uint32_t> ext_words(num_words, 0u);
|
||||
std::memcpy(ext_words.data(), name.data(), num_chars);
|
||||
std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(name);
|
||||
AddExtInstImport(std::unique_ptr<Instruction>(
|
||||
new Instruction(this, SpvOpExtInstImport, 0u, TakeNextId(),
|
||||
{{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "ir_builder.h"
|
||||
#include "ir_context.h"
|
||||
#include "iterator.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -328,8 +329,7 @@ bool LocalAccessChainConvertPass::AllExtensionsSupported() const {
|
||||
return false;
|
||||
// If any extension not in allowlist, return false
|
||||
for (auto& ei : get_module()->extensions()) {
|
||||
const char* extName =
|
||||
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
|
||||
const std::string extName = ei.GetInOperand(0).AsString();
|
||||
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
|
||||
return false;
|
||||
}
|
||||
@@ -339,11 +339,9 @@ bool LocalAccessChainConvertPass::AllExtensionsSupported() const {
|
||||
for (auto& inst : context()->module()->ext_inst_imports()) {
|
||||
assert(inst.opcode() == SpvOpExtInstImport &&
|
||||
"Expecting an import of an extension's instruction set.");
|
||||
const char* extension_name =
|
||||
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
|
||||
if (0 == std::strncmp(extension_name, "NonSemantic.", 12) &&
|
||||
0 != std::strncmp(extension_name, "NonSemantic.Shader.DebugInfo.100",
|
||||
32)) {
|
||||
const std::string extension_name = inst.GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
|
||||
extension_name != "NonSemantic.Shader.DebugInfo.100") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "source/opt/iterator.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -183,8 +184,7 @@ void LocalSingleBlockLoadStoreElimPass::Initialize() {
|
||||
bool LocalSingleBlockLoadStoreElimPass::AllExtensionsSupported() const {
|
||||
// If any extension not in allowlist, return false
|
||||
for (auto& ei : get_module()->extensions()) {
|
||||
const char* extName =
|
||||
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
|
||||
const std::string extName = ei.GetInOperand(0).AsString();
|
||||
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
|
||||
return false;
|
||||
}
|
||||
@@ -194,11 +194,9 @@ bool LocalSingleBlockLoadStoreElimPass::AllExtensionsSupported() const {
|
||||
for (auto& inst : context()->module()->ext_inst_imports()) {
|
||||
assert(inst.opcode() == SpvOpExtInstImport &&
|
||||
"Expecting an import of an extension's instruction set.");
|
||||
const char* extension_name =
|
||||
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
|
||||
if (0 == std::strncmp(extension_name, "NonSemantic.", 12) &&
|
||||
0 != std::strncmp(extension_name, "NonSemantic.Shader.DebugInfo.100",
|
||||
32)) {
|
||||
const std::string extension_name = inst.GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
|
||||
extension_name != "NonSemantic.Shader.DebugInfo.100") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "source/cfa.h"
|
||||
#include "source/latest_version_glsl_std_450_header.h"
|
||||
#include "source/opt/iterator.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -48,8 +49,7 @@ bool LocalSingleStoreElimPass::LocalSingleStoreElim(Function* func) {
|
||||
bool LocalSingleStoreElimPass::AllExtensionsSupported() const {
|
||||
// If any extension not in allowlist, return false
|
||||
for (auto& ei : get_module()->extensions()) {
|
||||
const char* extName =
|
||||
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
|
||||
const std::string extName = ei.GetInOperand(0).AsString();
|
||||
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
|
||||
return false;
|
||||
}
|
||||
@@ -59,11 +59,9 @@ bool LocalSingleStoreElimPass::AllExtensionsSupported() const {
|
||||
for (auto& inst : context()->module()->ext_inst_imports()) {
|
||||
assert(inst.opcode() == SpvOpExtInstImport &&
|
||||
"Expecting an import of an extension's instruction set.");
|
||||
const char* extension_name =
|
||||
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
|
||||
if (0 == std::strncmp(extension_name, "NonSemantic.", 12) &&
|
||||
0 != std::strncmp(extension_name, "NonSemantic.Shader.DebugInfo.100",
|
||||
32)) {
|
||||
const std::string extension_name = inst.GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
|
||||
extension_name != "NonSemantic.Shader.DebugInfo.100") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
6
3rdparty/spirv-tools/source/opt/module.cpp
vendored
6
3rdparty/spirv-tools/source/opt/module.cpp
vendored
@@ -139,7 +139,7 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
|
||||
// TODO(antiagainst): should we change the generator number?
|
||||
binary->push_back(header_.generator);
|
||||
binary->push_back(header_.bound);
|
||||
binary->push_back(header_.reserved);
|
||||
binary->push_back(header_.schema);
|
||||
|
||||
size_t bound_idx = binary->size() - 2;
|
||||
DebugScope last_scope(kNoDebugScope, kNoInlinedAt);
|
||||
@@ -260,9 +260,7 @@ bool Module::HasExplicitCapability(uint32_t cap) {
|
||||
|
||||
uint32_t Module::GetExtInstImportId(const char* extstr) {
|
||||
for (auto& ei : ext_inst_imports_)
|
||||
if (!strcmp(extstr,
|
||||
reinterpret_cast<const char*>(&(ei.GetInOperand(0).words[0]))))
|
||||
return ei.result_id();
|
||||
if (!ei.GetInOperand(0).AsString().compare(extstr)) return ei.result_id();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
6
3rdparty/spirv-tools/source/opt/module.h
vendored
6
3rdparty/spirv-tools/source/opt/module.h
vendored
@@ -36,7 +36,7 @@ struct ModuleHeader {
|
||||
uint32_t version;
|
||||
uint32_t generator;
|
||||
uint32_t bound;
|
||||
uint32_t reserved;
|
||||
uint32_t schema;
|
||||
};
|
||||
|
||||
// A SPIR-V module. It contains all the information for a SPIR-V module and
|
||||
@@ -61,7 +61,7 @@ class Module {
|
||||
}
|
||||
|
||||
// Returns the Id bound.
|
||||
uint32_t IdBound() { return header_.bound; }
|
||||
uint32_t IdBound() const { return header_.bound; }
|
||||
|
||||
// Returns the current Id bound and increases it to the next available value.
|
||||
// If the id bound has already reached its maximum value, then 0 is returned.
|
||||
@@ -141,6 +141,8 @@ class Module {
|
||||
inline uint32_t id_bound() const { return header_.bound; }
|
||||
|
||||
inline uint32_t version() const { return header_.version; }
|
||||
inline uint32_t generator() const { return header_.generator; }
|
||||
inline uint32_t schema() const { return header_.schema; }
|
||||
|
||||
inline void set_version(uint32_t v) { header_.version = v; }
|
||||
|
||||
|
||||
13
3rdparty/spirv-tools/source/opt/optimizer.cpp
vendored
13
3rdparty/spirv-tools/source/opt/optimizer.cpp
vendored
@@ -288,6 +288,8 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
|
||||
RegisterPass(CreateStripDebugInfoPass());
|
||||
} else if (pass_name == "strip-reflect") {
|
||||
RegisterPass(CreateStripReflectInfoPass());
|
||||
} else if (pass_name == "strip-nonsemantic") {
|
||||
RegisterPass(CreateStripNonSemanticInfoPass());
|
||||
} else if (pass_name == "set-spec-const-default-value") {
|
||||
if (pass_args.size() > 0) {
|
||||
auto spec_ids_vals =
|
||||
@@ -653,8 +655,12 @@ Optimizer::PassToken CreateStripDebugInfoPass() {
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateStripReflectInfoPass() {
|
||||
return CreateStripNonSemanticInfoPass();
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateStripNonSemanticInfoPass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(
|
||||
MakeUnique<opt::StripReflectInfoPass>());
|
||||
MakeUnique<opt::StripNonSemanticInfoPass>());
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateEliminateDeadFunctionsPass() {
|
||||
@@ -764,6 +770,11 @@ Optimizer::PassToken CreateLocalMultiStoreElimPass() {
|
||||
MakeUnique<opt::SSARewritePass>());
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateAggressiveDCEPass() {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(
|
||||
MakeUnique<opt::AggressiveDCEPass>(false));
|
||||
}
|
||||
|
||||
Optimizer::PassToken CreateAggressiveDCEPass(bool preserve_interface) {
|
||||
return MakeUnique<Optimizer::PassToken::Impl>(
|
||||
MakeUnique<opt::AggressiveDCEPass>(preserve_interface));
|
||||
|
||||
2
3rdparty/spirv-tools/source/opt/passes.h
vendored
2
3rdparty/spirv-tools/source/opt/passes.h
vendored
@@ -74,7 +74,7 @@
|
||||
#include "source/opt/ssa_rewrite_pass.h"
|
||||
#include "source/opt/strength_reduction_pass.h"
|
||||
#include "source/opt/strip_debug_info_pass.h"
|
||||
#include "source/opt/strip_reflect_info_pass.h"
|
||||
#include "source/opt/strip_nonsemantic_info_pass.h"
|
||||
#include "source/opt/unify_const_pass.h"
|
||||
#include "source/opt/upgrade_memory_model.h"
|
||||
#include "source/opt/vector_dce.h"
|
||||
|
||||
@@ -72,9 +72,8 @@ bool RemoveDuplicatesPass::RemoveDuplicatesExtInstImports() const {
|
||||
|
||||
std::unordered_map<std::string, SpvId> ext_inst_imports;
|
||||
for (auto* i = &*context()->ext_inst_import_begin(); i;) {
|
||||
auto res = ext_inst_imports.emplace(
|
||||
reinterpret_cast<const char*>(i->GetInOperand(0u).words.data()),
|
||||
i->result_id());
|
||||
auto res = ext_inst_imports.emplace(i->GetInOperand(0u).AsString(),
|
||||
i->result_id());
|
||||
if (res.second) {
|
||||
// Never seen before, keep it.
|
||||
i = i->NextNode();
|
||||
|
||||
@@ -112,8 +112,7 @@ bool ReplaceInvalidOpcodePass::RewriteFunction(Function* function,
|
||||
}
|
||||
Instruction* file_name =
|
||||
context()->get_def_use_mgr()->GetDef(file_name_id);
|
||||
const char* source = reinterpret_cast<const char*>(
|
||||
&file_name->GetInOperand(0).words[0]);
|
||||
const std::string source = file_name->GetInOperand(0).AsString();
|
||||
|
||||
// Get the line number and column number.
|
||||
uint32_t line_number =
|
||||
@@ -121,7 +120,7 @@ bool ReplaceInvalidOpcodePass::RewriteFunction(Function* function,
|
||||
uint32_t col_number = last_line_dbg_inst->GetSingleWordInOperand(2);
|
||||
|
||||
// Replace the instruction.
|
||||
ReplaceInstruction(inst, source, line_number, col_number);
|
||||
ReplaceInstruction(inst, source.c_str(), line_number, col_number);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "source/opt/strip_debug_info_pass.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -21,9 +22,8 @@ namespace opt {
|
||||
Pass::Status StripDebugInfoPass::Process() {
|
||||
bool uses_non_semantic_info = false;
|
||||
for (auto& inst : context()->module()->extensions()) {
|
||||
const char* ext_name =
|
||||
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
|
||||
if (0 == std::strcmp(ext_name, "SPV_KHR_non_semantic_info")) {
|
||||
const std::string ext_name = inst.GetInOperand(0).AsString();
|
||||
if (ext_name == "SPV_KHR_non_semantic_info") {
|
||||
uses_non_semantic_info = true;
|
||||
}
|
||||
}
|
||||
@@ -46,9 +46,10 @@ Pass::Status StripDebugInfoPass::Process() {
|
||||
if (use->opcode() == SpvOpExtInst) {
|
||||
auto ext_inst_set =
|
||||
def_use->GetDef(use->GetSingleWordInOperand(0u));
|
||||
const char* extension_name = reinterpret_cast<const char*>(
|
||||
&ext_inst_set->GetInOperand(0).words[0]);
|
||||
if (0 == std::strncmp(extension_name, "NonSemantic.", 12)) {
|
||||
const std::string extension_name =
|
||||
ext_inst_set->GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(extension_name,
|
||||
"NonSemantic.")) {
|
||||
// found a non-semantic use, return false as we cannot
|
||||
// remove this OpString
|
||||
return false;
|
||||
|
||||
@@ -12,18 +12,19 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/opt/strip_reflect_info_pass.h"
|
||||
#include "source/opt/strip_nonsemantic_info_pass.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
Pass::Status StripReflectInfoPass::Process() {
|
||||
Pass::Status StripNonSemanticInfoPass::Process() {
|
||||
bool modified = false;
|
||||
|
||||
std::vector<Instruction*> to_remove;
|
||||
@@ -32,7 +33,8 @@ Pass::Status StripReflectInfoPass::Process() {
|
||||
for (auto& inst : context()->module()->annotations()) {
|
||||
switch (inst.opcode()) {
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
if (inst.GetSingleWordInOperand(1) == SpvDecorationHlslSemanticGOOGLE) {
|
||||
if (inst.GetSingleWordInOperand(1) == SpvDecorationHlslSemanticGOOGLE ||
|
||||
inst.GetSingleWordInOperand(1) == SpvDecorationUserTypeGOOGLE) {
|
||||
to_remove.push_back(&inst);
|
||||
} else {
|
||||
other_uses_for_decorate_string = true;
|
||||
@@ -40,7 +42,8 @@ Pass::Status StripReflectInfoPass::Process() {
|
||||
break;
|
||||
|
||||
case SpvOpMemberDecorateStringGOOGLE:
|
||||
if (inst.GetSingleWordInOperand(2) == SpvDecorationHlslSemanticGOOGLE) {
|
||||
if (inst.GetSingleWordInOperand(2) == SpvDecorationHlslSemanticGOOGLE ||
|
||||
inst.GetSingleWordInOperand(2) == SpvDecorationUserTypeGOOGLE) {
|
||||
to_remove.push_back(&inst);
|
||||
} else {
|
||||
other_uses_for_decorate_string = true;
|
||||
@@ -60,33 +63,26 @@ Pass::Status StripReflectInfoPass::Process() {
|
||||
}
|
||||
|
||||
for (auto& inst : context()->module()->extensions()) {
|
||||
const char* ext_name =
|
||||
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
|
||||
if (0 == std::strcmp(ext_name, "SPV_GOOGLE_hlsl_functionality1")) {
|
||||
const std::string ext_name = inst.GetInOperand(0).AsString();
|
||||
if (ext_name == "SPV_GOOGLE_hlsl_functionality1") {
|
||||
to_remove.push_back(&inst);
|
||||
} else if (ext_name == "SPV_GOOGLE_user_type") {
|
||||
to_remove.push_back(&inst);
|
||||
} else if (!other_uses_for_decorate_string &&
|
||||
0 == std::strcmp(ext_name, "SPV_GOOGLE_decorate_string")) {
|
||||
ext_name == "SPV_GOOGLE_decorate_string") {
|
||||
to_remove.push_back(&inst);
|
||||
} else if (0 == std::strcmp(ext_name, "SPV_KHR_non_semantic_info")) {
|
||||
} else if (ext_name == "SPV_KHR_non_semantic_info") {
|
||||
to_remove.push_back(&inst);
|
||||
}
|
||||
}
|
||||
|
||||
// clear all debug data now if it hasn't been cleared already, to remove any
|
||||
// remaining OpString that may have been referenced by non-semantic extinsts
|
||||
for (auto& dbg : context()->debugs1()) to_remove.push_back(&dbg);
|
||||
for (auto& dbg : context()->debugs2()) to_remove.push_back(&dbg);
|
||||
for (auto& dbg : context()->debugs3()) to_remove.push_back(&dbg);
|
||||
for (auto& dbg : context()->ext_inst_debuginfo()) to_remove.push_back(&dbg);
|
||||
|
||||
// remove any extended inst imports that are non semantic
|
||||
std::unordered_set<uint32_t> non_semantic_sets;
|
||||
for (auto& inst : context()->module()->ext_inst_imports()) {
|
||||
assert(inst.opcode() == SpvOpExtInstImport &&
|
||||
"Expecting an import of an extension's instruction set.");
|
||||
const char* extension_name =
|
||||
reinterpret_cast<const char*>(&inst.GetInOperand(0).words[0]);
|
||||
if (0 == std::strncmp(extension_name, "NonSemantic.", 12)) {
|
||||
const std::string extension_name = inst.GetInOperand(0).AsString();
|
||||
if (spvtools::utils::starts_with(extension_name, "NonSemantic.")) {
|
||||
non_semantic_sets.insert(inst.result_id());
|
||||
to_remove.push_back(&inst);
|
||||
}
|
||||
@@ -103,19 +99,10 @@ Pass::Status StripReflectInfoPass::Process() {
|
||||
to_remove.push_back(inst);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
// OpName must come first, since they may refer to other debug instructions.
|
||||
// If they are after the instructions that refer to, then they will be killed
|
||||
// when that instruction is killed, which will lead to a double kill.
|
||||
std::sort(to_remove.begin(), to_remove.end(),
|
||||
[](Instruction* lhs, Instruction* rhs) -> bool {
|
||||
if (lhs->opcode() == SpvOpName && rhs->opcode() != SpvOpName)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
for (auto* inst : to_remove) {
|
||||
modified = true;
|
||||
context()->KillInst(inst);
|
||||
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SOURCE_OPT_STRIP_REFLECT_INFO_PASS_H_
|
||||
#define SOURCE_OPT_STRIP_REFLECT_INFO_PASS_H_
|
||||
#ifndef SOURCE_OPT_STRIP_NONSEMANTIC_INFO_PASS_H_
|
||||
#define SOURCE_OPT_STRIP_NONSEMANTIC_INFO_PASS_H_
|
||||
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/opt/module.h"
|
||||
@@ -23,9 +23,9 @@ namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// See optimizer.hpp for documentation.
|
||||
class StripReflectInfoPass : public Pass {
|
||||
class StripNonSemanticInfoPass : public Pass {
|
||||
public:
|
||||
const char* name() const override { return "strip-reflect"; }
|
||||
const char* name() const override { return "strip-nonsemantic"; }
|
||||
Status Process() override;
|
||||
|
||||
// Return the mask of preserved Analyses.
|
||||
@@ -41,4 +41,4 @@ class StripReflectInfoPass : public Pass {
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_OPT_STRIP_REFLECT_INFO_PASS_H_
|
||||
#endif // SOURCE_OPT_STRIP_NONSEMANTIC_INFO_PASS_H_
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "source/opt/log.h"
|
||||
#include "source/opt/reflect.h"
|
||||
#include "source/util/make_unique.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -349,11 +350,8 @@ uint32_t TypeManager::GetTypeInstruction(const Type* type) {
|
||||
}
|
||||
case Type::kOpaque: {
|
||||
const Opaque* opaque = type->AsOpaque();
|
||||
size_t size = opaque->name().size();
|
||||
// Convert to null-terminated packed UTF-8 string.
|
||||
std::vector<uint32_t> words(size / 4 + 1, 0);
|
||||
char* dst = reinterpret_cast<char*>(words.data());
|
||||
strncpy(dst, opaque->name().c_str(), size);
|
||||
std::vector<uint32_t> words = spvtools::utils::MakeVector(opaque->name());
|
||||
typeInst = MakeUnique<Instruction>(
|
||||
context(), SpvOpTypeOpaque, 0, id,
|
||||
std::initializer_list<Operand>{
|
||||
@@ -781,8 +779,7 @@ Type* TypeManager::RecordIfTypeDefinition(const Instruction& inst) {
|
||||
}
|
||||
} break;
|
||||
case SpvOpTypeOpaque: {
|
||||
const uint32_t* data = inst.GetInOperand(0).words.data();
|
||||
type = new Opaque(reinterpret_cast<const char*>(data));
|
||||
type = new Opaque(inst.GetInOperand(0).AsString());
|
||||
} break;
|
||||
case SpvOpTypePointer: {
|
||||
uint32_t pointee_type_id = inst.GetSingleWordInOperand(1);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/util/make_unique.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@@ -58,9 +59,7 @@ void UpgradeMemoryModel::UpgradeMemoryModelInstruction() {
|
||||
std::initializer_list<Operand>{
|
||||
{SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityVulkanMemoryModelKHR}}}));
|
||||
const std::string extension = "SPV_KHR_vulkan_memory_model";
|
||||
std::vector<uint32_t> words(extension.size() / 4 + 1, 0);
|
||||
char* dst = reinterpret_cast<char*>(words.data());
|
||||
strncpy(dst, extension.c_str(), extension.size());
|
||||
std::vector<uint32_t> words = spvtools::utils::MakeVector(extension);
|
||||
context()->AddExtension(
|
||||
MakeUnique<Instruction>(context(), SpvOpExtension, 0, 0,
|
||||
std::initializer_list<Operand>{
|
||||
@@ -85,8 +84,7 @@ void UpgradeMemoryModel::UpgradeInstructions() {
|
||||
if (ext_inst == GLSLstd450Modf || ext_inst == GLSLstd450Frexp) {
|
||||
auto import =
|
||||
get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u));
|
||||
if (reinterpret_cast<char*>(import->GetInOperand(0u).words.data()) ==
|
||||
std::string("GLSL.std.450")) {
|
||||
if (import->GetInOperand(0u).AsString() == "GLSL.std.450") {
|
||||
UpgradeExtInst(inst);
|
||||
}
|
||||
}
|
||||
|
||||
18
3rdparty/spirv-tools/source/spirv_target_env.cpp
vendored
18
3rdparty/spirv-tools/source/spirv_target_env.cpp
vendored
@@ -72,6 +72,8 @@ const char* spvTargetEnvDescription(spv_target_env env) {
|
||||
return "SPIR-V 1.5";
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
return "SPIR-V 1.5 (under Vulkan 1.2 semantics)";
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
return "SPIR-V 1.6";
|
||||
case SPV_ENV_MAX:
|
||||
assert(false && "Invalid target environment value.");
|
||||
break;
|
||||
@@ -113,6 +115,8 @@ uint32_t spvVersionForTargetEnv(spv_target_env env) {
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
return SPV_SPIRV_VERSION_WORD(1, 5);
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
return SPV_SPIRV_VERSION_WORD(1, 6);
|
||||
case SPV_ENV_MAX:
|
||||
assert(false && "Invalid target environment value.");
|
||||
break;
|
||||
@@ -131,6 +135,7 @@ static const std::pair<const char*, spv_target_env> spvTargetEnvNameMap[] = {
|
||||
{"spv1.3", SPV_ENV_UNIVERSAL_1_3},
|
||||
{"spv1.4", SPV_ENV_UNIVERSAL_1_4},
|
||||
{"spv1.5", SPV_ENV_UNIVERSAL_1_5},
|
||||
{"spv1.6", SPV_ENV_UNIVERSAL_1_6},
|
||||
{"opencl1.2embedded", SPV_ENV_OPENCL_EMBEDDED_1_2},
|
||||
{"opencl1.2", SPV_ENV_OPENCL_1_2},
|
||||
{"opencl2.0embedded", SPV_ENV_OPENCL_EMBEDDED_2_0},
|
||||
@@ -211,6 +216,7 @@ bool spvIsVulkanEnv(spv_target_env env) {
|
||||
case SPV_ENV_UNIVERSAL_1_3:
|
||||
case SPV_ENV_UNIVERSAL_1_4:
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
return false;
|
||||
case SPV_ENV_VULKAN_1_0:
|
||||
case SPV_ENV_VULKAN_1_1:
|
||||
@@ -244,6 +250,7 @@ bool spvIsOpenCLEnv(spv_target_env env) {
|
||||
case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
return false;
|
||||
case SPV_ENV_OPENCL_1_2:
|
||||
case SPV_ENV_OPENCL_EMBEDDED_1_2:
|
||||
@@ -284,6 +291,7 @@ bool spvIsOpenGLEnv(spv_target_env env) {
|
||||
case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
return false;
|
||||
case SPV_ENV_OPENGL_4_0:
|
||||
case SPV_ENV_OPENGL_4_1:
|
||||
@@ -321,6 +329,7 @@ bool spvIsValidEnv(spv_target_env env) {
|
||||
case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
case SPV_ENV_OPENGL_4_0:
|
||||
case SPV_ENV_OPENGL_4_1:
|
||||
case SPV_ENV_OPENGL_4_2:
|
||||
@@ -355,16 +364,17 @@ std::string spvLogStringForEnv(spv_target_env env) {
|
||||
}
|
||||
case SPV_ENV_VULKAN_1_0:
|
||||
case SPV_ENV_VULKAN_1_1:
|
||||
case SPV_ENV_VULKAN_1_1_SPIRV_1_4: {
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
return "Vulkan";
|
||||
case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
|
||||
case SPV_ENV_VULKAN_1_2: {
|
||||
return "Vulkan";
|
||||
}
|
||||
case SPV_ENV_UNIVERSAL_1_0:
|
||||
case SPV_ENV_UNIVERSAL_1_1:
|
||||
case SPV_ENV_UNIVERSAL_1_2:
|
||||
case SPV_ENV_UNIVERSAL_1_3:
|
||||
case SPV_ENV_UNIVERSAL_1_4:
|
||||
case SPV_ENV_UNIVERSAL_1_5: {
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_UNIVERSAL_1_6: {
|
||||
return "Universal";
|
||||
}
|
||||
case SPV_ENV_WEBGPU_0:
|
||||
|
||||
1
3rdparty/spirv-tools/source/table.cpp
vendored
1
3rdparty/spirv-tools/source/table.cpp
vendored
@@ -41,6 +41,7 @@ spv_context spvContextCreate(spv_target_env env) {
|
||||
case SPV_ENV_UNIVERSAL_1_4:
|
||||
case SPV_ENV_UNIVERSAL_1_5:
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
case SPV_ENV_UNIVERSAL_1_6:
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
|
||||
11
3rdparty/spirv-tools/source/text_handler.cpp
vendored
11
3rdparty/spirv-tools/source/text_handler.cpp
vendored
@@ -29,6 +29,7 @@
|
||||
#include "source/util/bitutils.h"
|
||||
#include "source/util/hex_float.h"
|
||||
#include "source/util/parse_number.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace {
|
||||
@@ -307,14 +308,8 @@ spv_result_t AssemblyContext::binaryEncodeString(const char* value,
|
||||
<< SPV_LIMIT_INSTRUCTION_WORD_COUNT_MAX << " words.";
|
||||
}
|
||||
|
||||
pInst->words.resize(newWordCount);
|
||||
|
||||
// Make sure all the bytes in the last word are 0, in case we only
|
||||
// write a partial word at the end.
|
||||
pInst->words.back() = 0;
|
||||
|
||||
char* dest = (char*)&pInst->words[oldWordCount];
|
||||
strncpy(dest, value, length + 1);
|
||||
pInst->words.reserve(newWordCount);
|
||||
spvtools::utils::AppendToVector(value, &pInst->words);
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
2
3rdparty/spirv-tools/source/util/hex_float.h
vendored
2
3rdparty/spirv-tools/source/util/hex_float.h
vendored
@@ -199,7 +199,7 @@ bool operator==(const FloatProxy<T>& first, const FloatProxy<T>& second) {
|
||||
// Reads a FloatProxy value as a normal float from a stream.
|
||||
template <typename T>
|
||||
std::istream& operator>>(std::istream& is, FloatProxy<T>& value) {
|
||||
T float_val;
|
||||
T float_val = static_cast<T>(0.0);
|
||||
is >> float_val;
|
||||
value = FloatProxy<T>(float_val);
|
||||
return is;
|
||||
|
||||
63
3rdparty/spirv-tools/source/util/string_utils.h
vendored
63
3rdparty/spirv-tools/source/util/string_utils.h
vendored
@@ -16,6 +16,8 @@
|
||||
#define SOURCE_UTIL_STRING_UTILS_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -44,9 +46,10 @@ std::string CardinalToOrdinal(size_t cardinal);
|
||||
// string will be empty.
|
||||
std::pair<std::string, std::string> SplitFlagArgs(const std::string& flag);
|
||||
|
||||
// Encodes a string as a sequence of words, using the SPIR-V encoding.
|
||||
inline std::vector<uint32_t> MakeVector(std::string input) {
|
||||
std::vector<uint32_t> result;
|
||||
// Encodes a string as a sequence of words, using the SPIR-V encoding, appending
|
||||
// to an existing vector.
|
||||
inline void AppendToVector(const std::string& input,
|
||||
std::vector<uint32_t>* result) {
|
||||
uint32_t word = 0;
|
||||
size_t num_bytes = input.size();
|
||||
// SPIR-V strings are null-terminated. The byte_index == num_bytes
|
||||
@@ -56,24 +59,36 @@ inline std::vector<uint32_t> MakeVector(std::string input) {
|
||||
(byte_index < num_bytes ? uint8_t(input[byte_index]) : uint8_t(0));
|
||||
word |= (new_byte << (8 * (byte_index % sizeof(uint32_t))));
|
||||
if (3 == (byte_index % sizeof(uint32_t))) {
|
||||
result.push_back(word);
|
||||
result->push_back(word);
|
||||
word = 0;
|
||||
}
|
||||
}
|
||||
// Emit a trailing partial word.
|
||||
if ((num_bytes + 1) % sizeof(uint32_t)) {
|
||||
result.push_back(word);
|
||||
result->push_back(word);
|
||||
}
|
||||
}
|
||||
|
||||
// Encodes a string as a sequence of words, using the SPIR-V encoding.
|
||||
inline std::vector<uint32_t> MakeVector(const std::string& input) {
|
||||
std::vector<uint32_t> result;
|
||||
AppendToVector(input, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Decode a string from a sequence of words, using the SPIR-V encoding.
|
||||
template <class VectorType>
|
||||
inline std::string MakeString(const VectorType& words) {
|
||||
// Decode a string from a sequence of words between first and last, using the
|
||||
// SPIR-V encoding. Assert that a terminating 0-byte was found (unless
|
||||
// assert_found_terminating_null is passed as false).
|
||||
template <class InputIt>
|
||||
inline std::string MakeString(InputIt first, InputIt last,
|
||||
bool assert_found_terminating_null = true) {
|
||||
std::string result;
|
||||
constexpr size_t kCharsPerWord = sizeof(*first);
|
||||
static_assert(kCharsPerWord == 4, "expect 4-byte word");
|
||||
|
||||
for (uint32_t word : words) {
|
||||
for (int byte_index = 0; byte_index < 4; byte_index++) {
|
||||
for (InputIt pos = first; pos != last; ++pos) {
|
||||
uint32_t word = *pos;
|
||||
for (size_t byte_index = 0; byte_index < kCharsPerWord; byte_index++) {
|
||||
uint32_t extracted_word = (word >> (8 * byte_index)) & 0xFF;
|
||||
char c = static_cast<char>(extracted_word);
|
||||
if (c == 0) {
|
||||
@@ -82,9 +97,33 @@ inline std::string MakeString(const VectorType& words) {
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
assert(false && "Did not find terminating null for the string.");
|
||||
assert(!assert_found_terminating_null &&
|
||||
"Did not find terminating null for the string.");
|
||||
(void)assert_found_terminating_null; /* No unused parameters in release
|
||||
builds. */
|
||||
return result;
|
||||
} // namespace utils
|
||||
}
|
||||
|
||||
// Decode a string from a sequence of words in a vector, using the SPIR-V
|
||||
// encoding.
|
||||
template <class VectorType>
|
||||
inline std::string MakeString(const VectorType& words,
|
||||
bool assert_found_terminating_null = true) {
|
||||
return MakeString(words.cbegin(), words.cend(),
|
||||
assert_found_terminating_null);
|
||||
}
|
||||
|
||||
// Decode a string from array words, consuming up to count words, using the
|
||||
// SPIR-V encoding.
|
||||
inline std::string MakeString(const uint32_t* words, size_t num_words,
|
||||
bool assert_found_terminating_null = true) {
|
||||
return MakeString(words, words + num_words, assert_found_terminating_null);
|
||||
}
|
||||
|
||||
// Check if str starts with prefix (only included since C++20)
|
||||
inline bool starts_with(const std::string& str, const char* prefix) {
|
||||
return 0 == str.compare(0, std::strlen(prefix), prefix);
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace spvtools
|
||||
|
||||
10
3rdparty/spirv-tools/source/val/instruction.cpp
vendored
10
3rdparty/spirv-tools/source/val/instruction.cpp
vendored
@@ -16,6 +16,9 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "source/binary.h"
|
||||
#include "source/util/string_utils.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace val {
|
||||
|
||||
@@ -41,5 +44,12 @@ bool operator==(const Instruction& lhs, uint32_t rhs) {
|
||||
return lhs.id() == rhs;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string Instruction::GetOperandAs<std::string>(size_t index) const {
|
||||
const spv_parsed_operand_t& o = operands_.at(index);
|
||||
assert(o.offset + o.num_words <= inst_.num_words);
|
||||
return spvtools::utils::MakeString(words_.data() + o.offset, o.num_words);
|
||||
}
|
||||
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
||||
@@ -133,6 +133,9 @@ bool operator<(const Instruction& lhs, uint32_t rhs);
|
||||
bool operator==(const Instruction& lhs, const Instruction& rhs);
|
||||
bool operator==(const Instruction& lhs, uint32_t rhs);
|
||||
|
||||
template <>
|
||||
std::string Instruction::GetOperandAs<std::string>(size_t index) const;
|
||||
|
||||
} // namespace val
|
||||
} // namespace spvtools
|
||||
|
||||
|
||||
9
3rdparty/spirv-tools/source/val/validate.cpp
vendored
9
3rdparty/spirv-tools/source/val/validate.cpp
vendored
@@ -219,9 +219,7 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
|
||||
if (inst->opcode() == SpvOpEntryPoint) {
|
||||
const auto entry_point = inst->GetOperandAs<uint32_t>(1);
|
||||
const auto execution_model = inst->GetOperandAs<SpvExecutionModel>(0);
|
||||
const char* str = reinterpret_cast<const char*>(
|
||||
inst->words().data() + inst->operand(2).offset);
|
||||
const std::string desc_name(str);
|
||||
const std::string desc_name = inst->GetOperandAs<std::string>(2);
|
||||
|
||||
ValidationState_t::EntryPointDescription desc;
|
||||
desc.name = desc_name;
|
||||
@@ -237,9 +235,8 @@ spv_result_t ValidateBinaryUsingContextAndValidationState(
|
||||
for (const Instruction* check_inst : visited_entry_points) {
|
||||
const auto check_execution_model =
|
||||
check_inst->GetOperandAs<SpvExecutionModel>(0);
|
||||
const char* check_str = reinterpret_cast<const char*>(
|
||||
check_inst->words().data() + inst->operand(2).offset);
|
||||
const std::string check_name(check_str);
|
||||
const std::string check_name =
|
||||
check_inst->GetOperandAs<std::string>(2);
|
||||
|
||||
if (desc_name == check_name &&
|
||||
execution_model == check_execution_model) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "source/cfa.h"
|
||||
#include "source/opcode.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/spirv_validator_options.h"
|
||||
#include "source/val/basic_block.h"
|
||||
@@ -191,6 +192,12 @@ spv_result_t ValidateBranchConditional(ValidationState_t& _,
|
||||
"ID of an OpLabel instruction";
|
||||
}
|
||||
|
||||
if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) && true_id == false_id) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "In SPIR-V 1.6 or later, True Label and False Label must be "
|
||||
"different labels";
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "source/binary.h"
|
||||
#include "source/diagnostic.h"
|
||||
#include "source/opcode.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/spirv_validator_options.h"
|
||||
#include "source/util/string_utils.h"
|
||||
#include "source/val/validate_scopes.h"
|
||||
#include "source/val/validation_state.h"
|
||||
|
||||
@@ -96,6 +98,14 @@ bool isBuiltInStruct(uint32_t struct_id, ValidationState_t& vstate) {
|
||||
});
|
||||
}
|
||||
|
||||
// Returns true if the given structure type has a Block decoration.
|
||||
bool isBlock(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 SpvDecorationBlock == d.dec_type(); });
|
||||
}
|
||||
|
||||
// Returns true if the given ID has the Import LinkageAttributes decoration.
|
||||
bool hasImportLinkageAttribute(uint32_t id, ValidationState_t& vstate) {
|
||||
const auto& decorations = vstate.id_decorations(id);
|
||||
@@ -702,7 +712,7 @@ spv_result_t CheckBuiltInVariable(uint32_t var_id, ValidationState_t& vstate) {
|
||||
if (d.dec_type() == SpvDecorationLocation ||
|
||||
d.dec_type() == SpvDecorationComponent) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
|
||||
<< "A BuiltIn variable (id " << var_id
|
||||
<< vstate.VkErrorID(4915) << "A BuiltIn variable (id " << var_id
|
||||
<< ") cannot have any Location or Component decorations";
|
||||
}
|
||||
}
|
||||
@@ -714,8 +724,8 @@ spv_result_t CheckBuiltInVariable(uint32_t var_id, ValidationState_t& vstate) {
|
||||
spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
|
||||
for (uint32_t entry_point : vstate.entry_points()) {
|
||||
const auto& descs = vstate.entry_point_descriptions(entry_point);
|
||||
int num_builtin_inputs = 0;
|
||||
int num_builtin_outputs = 0;
|
||||
int num_builtin_block_inputs = 0;
|
||||
int num_builtin_block_outputs = 0;
|
||||
int num_workgroup_variables = 0;
|
||||
int num_workgroup_variables_with_block = 0;
|
||||
int num_workgroup_variables_with_aliased = 0;
|
||||
@@ -766,9 +776,20 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
|
||||
Instruction* type_instr = vstate.FindDef(type_id);
|
||||
if (type_instr && SpvOpTypeStruct == type_instr->opcode() &&
|
||||
isBuiltInStruct(type_id, vstate)) {
|
||||
if (storage_class == SpvStorageClassInput) ++num_builtin_inputs;
|
||||
if (storage_class == SpvStorageClassOutput) ++num_builtin_outputs;
|
||||
if (num_builtin_inputs > 1 || num_builtin_outputs > 1) break;
|
||||
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 == SpvStorageClassInput) ++num_builtin_block_inputs;
|
||||
if (storage_class == SpvStorageClassOutput)
|
||||
++num_builtin_block_outputs;
|
||||
if (num_builtin_block_inputs > 1 || num_builtin_block_outputs > 1)
|
||||
break;
|
||||
if (auto error = CheckBuiltInVariable(interface, vstate))
|
||||
return error;
|
||||
} else if (isBuiltInVar(interface, vstate)) {
|
||||
@@ -786,7 +807,7 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_builtin_inputs > 1 || num_builtin_outputs > 1) {
|
||||
if (num_builtin_block_inputs > 1 || num_builtin_block_outputs > 1) {
|
||||
return vstate.diag(SPV_ERROR_INVALID_BINARY,
|
||||
vstate.FindDef(entry_point))
|
||||
<< "There must be at most one object per Storage Class that can "
|
||||
@@ -798,8 +819,8 @@ spv_result_t CheckDecorationsOfEntryPoints(ValidationState_t& vstate) {
|
||||
// targeted by an OpEntryPoint instruction
|
||||
for (auto& decoration : vstate.id_decorations(entry_point)) {
|
||||
if (SpvDecorationLinkageAttributes == decoration.dec_type()) {
|
||||
const char* linkage_name =
|
||||
reinterpret_cast<const char*>(&decoration.params()[0]);
|
||||
const std::string linkage_name =
|
||||
spvtools::utils::MakeString(decoration.params());
|
||||
return vstate.diag(SPV_ERROR_INVALID_BINARY,
|
||||
vstate.FindDef(entry_point))
|
||||
<< "The LinkageAttributes Decoration (Linkage name: "
|
||||
|
||||
@@ -280,8 +280,7 @@ spv_result_t ValidateClspvReflectionKernel(ValidationState_t& _,
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
|
||||
}
|
||||
|
||||
const std::string name_str = reinterpret_cast<const char*>(
|
||||
name->words().data() + name->operands()[1].offset);
|
||||
const std::string name_str = name->GetOperandAs<std::string>(1);
|
||||
bool found = false;
|
||||
for (auto& desc : _.entry_point_descriptions(kernel_id)) {
|
||||
if (name_str == desc.name) {
|
||||
@@ -740,9 +739,9 @@ spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) {
|
||||
spv_result_t ValidateExtInstImport(ValidationState_t& _,
|
||||
const Instruction* inst) {
|
||||
const auto name_id = 1;
|
||||
if (!_.HasExtension(kSPV_KHR_non_semantic_info)) {
|
||||
const std::string name(reinterpret_cast<const char*>(
|
||||
inst->words().data() + inst->operands()[name_id].offset));
|
||||
if (_.version() <= SPV_SPIRV_VERSION_WORD(1, 5) &&
|
||||
!_.HasExtension(kSPV_KHR_non_semantic_info)) {
|
||||
const std::string name = inst->GetOperandAs<std::string>(name_id);
|
||||
if (name.find("NonSemantic.") == 0) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||
<< "NonSemantic extended instruction sets cannot be declared "
|
||||
@@ -774,7 +773,7 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
|
||||
assert(import_inst);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << reinterpret_cast<const char*>(import_inst->words().data() + 2);
|
||||
ss << import_inst->GetOperandAs<std::string>(1);
|
||||
ss << " ";
|
||||
ss << desc->name;
|
||||
|
||||
@@ -3264,8 +3263,7 @@ spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
|
||||
}
|
||||
} else if (ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION) {
|
||||
auto import_inst = _.FindDef(inst->GetOperandAs<uint32_t>(2));
|
||||
const std::string name(reinterpret_cast<const char*>(
|
||||
import_inst->words().data() + import_inst->operands()[1].offset));
|
||||
const std::string name = import_inst->GetOperandAs<std::string>(1);
|
||||
const std::string reflection = "NonSemantic.ClspvReflection.";
|
||||
char* end_ptr;
|
||||
auto version_string = name.substr(reflection.size());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
|
||||
// reserved.
|
||||
//
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "source/diagnostic.h"
|
||||
#include "source/opcode.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/util/bitutils.h"
|
||||
#include "source/val/instruction.h"
|
||||
@@ -71,6 +72,7 @@ bool CheckAllImageOperandsHandled() {
|
||||
// blocks other PRs.
|
||||
// https://github.com/KhronosGroup/SPIRV-Tools/issues/4565
|
||||
case SpvImageOperandsOffsetsMask:
|
||||
case SpvImageOperandsNontemporalMask:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -630,6 +632,10 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
||||
// TODO: add validation
|
||||
}
|
||||
|
||||
if (mask & SpvImageOperandsNontemporalMask) {
|
||||
// Checked elsewhere: SPIR-V 1.6 version or later.
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -915,6 +921,13 @@ spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
|
||||
"operand set to 0 or 1";
|
||||
}
|
||||
|
||||
// This covers both OpTypeSampledImage and OpSampledImage.
|
||||
if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) && info.dim == SpvDimBuffer) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "In SPIR-V 1.6 or later, sampled image dimension must not be "
|
||||
"Buffer";
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ spv_result_t NumConsumedLocations(ValidationState_t& _, const Instruction* type,
|
||||
// Members cannot have location decorations at this point.
|
||||
if (_.HasDecoration(type->id(), SpvDecorationLocation)) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, type)
|
||||
<< "Members cannot be assigned a location";
|
||||
<< _.VkErrorID(4918) << "Members cannot be assigned a location";
|
||||
}
|
||||
|
||||
// Structs consume locations equal to the sum of the locations consumed
|
||||
@@ -326,8 +326,9 @@ spv_result_t GetLocationsForVariable(
|
||||
// Only block-decorated structs don't need a location on the variable.
|
||||
const bool is_block = _.HasDecoration(type_id, SpvDecorationBlock);
|
||||
if (!has_location && !is_block) {
|
||||
const auto vuid = (type->opcode() == SpvOpTypeStruct) ? 4917 : 4916;
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, variable)
|
||||
<< "Variable must be decorated with a location";
|
||||
<< _.VkErrorID(vuid) << "Variable must be decorated with a location";
|
||||
}
|
||||
|
||||
const std::string storage_class = is_output ? "output" : "input";
|
||||
@@ -411,7 +412,7 @@ spv_result_t GetLocationsForVariable(
|
||||
auto where = member_locations.find(i - 1);
|
||||
if (where == member_locations.end()) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, type)
|
||||
<< "Member index " << i - 1
|
||||
<< _.VkErrorID(4919) << "Member index " << i - 1
|
||||
<< " is missing a location assignment";
|
||||
}
|
||||
|
||||
@@ -476,6 +477,9 @@ spv_result_t ValidateLocations(ValidationState_t& _,
|
||||
const Instruction* entry_point) {
|
||||
// According to Vulkan 14.1 only the following execution models have
|
||||
// locations assigned.
|
||||
// TODO(dneto): SPV_NV_ray_tracing also uses locations on interface variables,
|
||||
// in other shader stages. Similarly, the *provisional* version of
|
||||
// SPV_KHR_ray_tracing did as well, but not the final version.
|
||||
switch (entry_point->GetOperandAs<SpvExecutionModel>(0)) {
|
||||
case SpvExecutionModelVertex:
|
||||
case SpvExecutionModelTessellationControl:
|
||||
|
||||
@@ -175,8 +175,18 @@ ValidationState_t::ValidationState_t(const spv_const_context ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// LocalSizeId is always allowed in non-Vulkan environments.
|
||||
features_.env_allow_localsizeid = !spvIsVulkanEnv(env);
|
||||
// LocalSizeId is only disallowed without maintainence4.
|
||||
switch (env) {
|
||||
case SPV_ENV_VULKAN_1_0:
|
||||
case SPV_ENV_VULKAN_1_1:
|
||||
case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
|
||||
case SPV_ENV_VULKAN_1_2:
|
||||
features_.env_allow_localsizeid = false;
|
||||
break;
|
||||
default:
|
||||
features_.env_allow_localsizeid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Only attempt to count if we have words, otherwise let the other validation
|
||||
// fail and generate an error.
|
||||
@@ -389,6 +399,15 @@ void ValidationState_t::RegisterCapability(SpvCapability cap) {
|
||||
features_.variable_pointers_storage_buffer = true;
|
||||
break;
|
||||
default:
|
||||
// TODO(dneto): For now don't validate SPV_NV_ray_tracing, which uses
|
||||
// capability SpvCapabilityRayTracingNV.
|
||||
// SpvCapabilityRayTracingProvisionalKHR would need the same treatment.
|
||||
// One of the differences going from SPV_KHR_ray_tracing from
|
||||
// provisional to final spec was the provisional spec uses Locations
|
||||
// for variables in certain storage classes, just like the
|
||||
// SPV_NV_ray_tracing extension. So it mimics the NVIDIA extension.
|
||||
// The final SPV_KHR_ray_tracing uses a different capability token
|
||||
// number, so it doesn't fall into this case.
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -497,15 +516,13 @@ void ValidationState_t::RegisterDebugInstruction(const Instruction* inst) {
|
||||
switch (inst->opcode()) {
|
||||
case SpvOpName: {
|
||||
const auto target = inst->GetOperandAs<uint32_t>(0);
|
||||
const auto* str = reinterpret_cast<const char*>(inst->words().data() +
|
||||
inst->operand(1).offset);
|
||||
const std::string str = inst->GetOperandAs<std::string>(1);
|
||||
AssignNameToId(target, str);
|
||||
break;
|
||||
}
|
||||
case SpvOpMemberName: {
|
||||
const auto target = inst->GetOperandAs<uint32_t>(0);
|
||||
const auto* str = reinterpret_cast<const char*>(inst->words().data() +
|
||||
inst->operand(2).offset);
|
||||
const std::string str = inst->GetOperandAs<std::string>(2);
|
||||
AssignNameToId(target, str);
|
||||
break;
|
||||
}
|
||||
@@ -1867,6 +1884,16 @@ std::string ValidationState_t::VkErrorID(uint32_t id,
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04733);
|
||||
case 4780:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Result-04780);
|
||||
case 4915:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Location-04915);
|
||||
case 4916:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Location-04916);
|
||||
case 4917:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Location-04917);
|
||||
case 4918:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Location-04918);
|
||||
case 4919:
|
||||
return VUID_WRAP(VUID-StandaloneSpirv-Location-04919);
|
||||
default:
|
||||
return ""; // unknown id
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user