diff --git a/include/SPIRV/CInterface/spirv_c_interface.cpp b/include/SPIRV/CInterface/spirv_c_interface.cpp deleted file mode 100644 index 631d19d7..00000000 --- a/include/SPIRV/CInterface/spirv_c_interface.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/** - This code is based on the glslang_c_interface implementation by Viktor Latypov -**/ - -/** -BSD 2-Clause License - -Copyright (c) 2019, Viktor Latypov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**/ - -#include "glslang/Include/glslang_c_interface.h" - -#include -#include "glslang/Public/ShaderLang.h" -#include "SPIRV/GlslangToSpv.h" -#include "SPIRV/Logger.h" -#include "SPIRV/SpvTools.h" - -static_assert(sizeof(glslang_spv_options_t) == sizeof(glslang::SpvOptions), ""); - -typedef struct glslang_program_s { - glslang::TProgram* program; - std::vector spirv; - std::string loggerMessages; -} glslang_program_t; - -static EShLanguage c_shader_stage(glslang_stage_t stage) -{ - switch (stage) { - case GLSLANG_STAGE_VERTEX: - return EShLangVertex; - case GLSLANG_STAGE_TESSCONTROL: - return EShLangTessControl; - case GLSLANG_STAGE_TESSEVALUATION: - return EShLangTessEvaluation; - case GLSLANG_STAGE_GEOMETRY: - return EShLangGeometry; - case GLSLANG_STAGE_FRAGMENT: - return EShLangFragment; - case GLSLANG_STAGE_COMPUTE: - return EShLangCompute; - case GLSLANG_STAGE_RAYGEN: - return EShLangRayGen; - case GLSLANG_STAGE_INTERSECT: - return EShLangIntersect; - case GLSLANG_STAGE_ANYHIT: - return EShLangAnyHit; - case GLSLANG_STAGE_CLOSESTHIT: - return EShLangClosestHit; - case GLSLANG_STAGE_MISS: - return EShLangMiss; - case GLSLANG_STAGE_CALLABLE: - return EShLangCallable; - case GLSLANG_STAGE_TASK: - return EShLangTask; - case GLSLANG_STAGE_MESH: - return EShLangMesh; - default: - break; - } - return EShLangCount; -} - -GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage) -{ - glslang_spv_options_t spv_options {}; - spv_options.disable_optimizer = true; - spv_options.validate = true; - - glslang_program_SPIRV_generate_with_options(program, stage, &spv_options); -} - -GLSLANG_EXPORT void glslang_program_SPIRV_generate_with_options(glslang_program_t* program, glslang_stage_t stage, glslang_spv_options_t* spv_options) { - spv::SpvBuildLogger logger; - - const glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage)); - - program->spirv.clear(); - - glslang::GlslangToSpv(*intermediate, program->spirv, &logger, reinterpret_cast(spv_options)); - - program->loggerMessages = logger.getAllMessages(); -} - -GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program) { return program->spirv.size(); } - -GLSLANG_EXPORT void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int* out) -{ - memcpy(out, program->spirv.data(), program->spirv.size() * sizeof(unsigned int)); -} - -GLSLANG_EXPORT unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program) -{ - return program->spirv.data(); -} - -GLSLANG_EXPORT const char* glslang_program_SPIRV_get_messages(glslang_program_t* program) -{ - return program->loggerMessages.empty() ? nullptr : program->loggerMessages.c_str(); -} diff --git a/include/SPIRV/CMakeLists.txt b/include/SPIRV/CMakeLists.txt deleted file mode 100644 index b5fd5b6c..00000000 --- a/include/SPIRV/CMakeLists.txt +++ /dev/null @@ -1,134 +0,0 @@ -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -set(SPIRV_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/GlslangToSpv.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/InReadableOrder.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Logger.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/SpvBuilder.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/SpvPostProcess.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/doc.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/SpvTools.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/CInterface/spirv_c_interface.cpp - PARENT_SCOPE) - -set(SPVREMAP_SOURCES - SPVRemapper.cpp - doc.cpp) - -set(SPIRV_HEADERS - ${CMAKE_CURRENT_SOURCE_DIR}/bitutils.h - ${CMAKE_CURRENT_SOURCE_DIR}/spirv.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/GLSL.std.450.h - ${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.EXT.h - ${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.KHR.h - ${CMAKE_CURRENT_SOURCE_DIR}/GlslangToSpv.h - ${CMAKE_CURRENT_SOURCE_DIR}/hex_float.h - ${CMAKE_CURRENT_SOURCE_DIR}/Logger.h - ${CMAKE_CURRENT_SOURCE_DIR}/SpvBuilder.h - ${CMAKE_CURRENT_SOURCE_DIR}/spvIR.h - ${CMAKE_CURRENT_SOURCE_DIR}/doc.h - ${CMAKE_CURRENT_SOURCE_DIR}/SpvTools.h - ${CMAKE_CURRENT_SOURCE_DIR}/disassemble.h - ${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.AMD.h - ${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.NV.h - ${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.ARM.h - ${CMAKE_CURRENT_SOURCE_DIR}/GLSL.ext.QCOM.h - ${CMAKE_CURRENT_SOURCE_DIR}/NonSemanticDebugPrintf.h - ${CMAKE_CURRENT_SOURCE_DIR}/NonSemanticShaderDebugInfo100.h - PARENT_SCOPE) - -set(SPVREMAP_HEADERS - SPVRemapper.h - doc.h) - -set(PUBLIC_HEADERS - GlslangToSpv.h - disassemble.h - Logger.h - spirv.hpp - SPVRemapper.h - SpvTools.h) - -add_library(SPIRV ${LIB_TYPE} ${CMAKE_CURRENT_SOURCE_DIR}/../glslang/stub.cpp) -add_library(glslang::SPIRV ALIAS SPIRV) -set_target_properties(SPIRV PROPERTIES - FOLDER glslang - POSITION_INDEPENDENT_CODE ON - VERSION "${GLSLANG_VERSION}" - SOVERSION "${GLSLANG_VERSION_MAJOR}") -target_include_directories(SPIRV PUBLIC - $ - $) - -if (ENABLE_SPVREMAPPER) - add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) - add_library(glslang::SPVRemapper ALIAS SPVRemapper) - set_target_properties(SPVRemapper PROPERTIES - FOLDER glslang - POSITION_INDEPENDENT_CODE ON - VERSION "${GLSLANG_VERSION}" - SOVERSION "${GLSLANG_VERSION_MAJOR}") - glslang_only_export_explicit_symbols(SPVRemapper) -endif() - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(SPIRV PROPERTIES PREFIX "") - if (ENABLE_SPVREMAPPER) - set_target_properties(SPVRemapper PROPERTIES PREFIX "") - endif() -endif() - -if(ENABLE_OPT) - target_link_libraries(SPIRV PRIVATE glslang PUBLIC SPIRV-Tools-opt) - target_include_directories(SPIRV PUBLIC - $) -else() - target_link_libraries(SPIRV PRIVATE glslang) -endif() - -if(WIN32) - source_group("Source" FILES ${SOURCES} ${HEADERS}) - source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) -endif() - -if(GLSLANG_ENABLE_INSTALL) - if (ENABLE_SPVREMAPPER) - install(TARGETS SPVRemapper EXPORT glslang-targets) - endif() - - install(TARGETS SPIRV EXPORT glslang-targets) - - install(FILES ${PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/SPIRV/) -endif() diff --git a/include/SPIRV/GLSL.ext.AMD.h b/include/SPIRV/GLSL.ext.AMD.h deleted file mode 100644 index 009d2f1c..00000000 --- a/include/SPIRV/GLSL.ext.AMD.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextAMD_H -#define GLSLextAMD_H - -static const int GLSLextAMDVersion = 100; -static const int GLSLextAMDRevision = 7; - -// SPV_AMD_shader_ballot -static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; - -enum ShaderBallotAMD { - ShaderBallotBadAMD = 0, // Don't use - - SwizzleInvocationsAMD = 1, - SwizzleInvocationsMaskedAMD = 2, - WriteInvocationAMD = 3, - MbcntAMD = 4, - - ShaderBallotCountAMD -}; - -// SPV_AMD_shader_trinary_minmax -static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; - -enum ShaderTrinaryMinMaxAMD { - ShaderTrinaryMinMaxBadAMD = 0, // Don't use - - FMin3AMD = 1, - UMin3AMD = 2, - SMin3AMD = 3, - FMax3AMD = 4, - UMax3AMD = 5, - SMax3AMD = 6, - FMid3AMD = 7, - UMid3AMD = 8, - SMid3AMD = 9, - - ShaderTrinaryMinMaxCountAMD -}; - -// SPV_AMD_shader_explicit_vertex_parameter -static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; - -enum ShaderExplicitVertexParameterAMD { - ShaderExplicitVertexParameterBadAMD = 0, // Don't use - - InterpolateAtVertexAMD = 1, - - ShaderExplicitVertexParameterCountAMD -}; - -// SPV_AMD_gcn_shader -static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; - -enum GcnShaderAMD { - GcnShaderBadAMD = 0, // Don't use - - CubeFaceIndexAMD = 1, - CubeFaceCoordAMD = 2, - TimeAMD = 3, - - GcnShaderCountAMD -}; - -// SPV_AMD_gpu_shader_half_float -static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; - -// SPV_AMD_texture_gather_bias_lod -static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; - -// SPV_AMD_gpu_shader_int16 -static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; - -// SPV_AMD_shader_image_load_store_lod -static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; - -// SPV_AMD_shader_fragment_mask -static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; - -// SPV_AMD_gpu_shader_half_float_fetch -static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; - -#endif // #ifndef GLSLextAMD_H diff --git a/include/SPIRV/GLSL.ext.ARM.h b/include/SPIRV/GLSL.ext.ARM.h deleted file mode 100644 index 14425be1..00000000 --- a/include/SPIRV/GLSL.ext.ARM.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -** Copyright (c) 2022 ARM Limited -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextARM_H -#define GLSLextARM_H - -static const int GLSLextARMVersion = 100; -static const int GLSLextARMRevision = 1; - -static const char * const E_SPV_ARM_core_builtins = "SPV_ARM_core_builtins"; - -#endif // #ifndef GLSLextARM_H diff --git a/include/SPIRV/GLSL.ext.EXT.h b/include/SPIRV/GLSL.ext.EXT.h deleted file mode 100644 index 07f3c302..00000000 --- a/include/SPIRV/GLSL.ext.EXT.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextEXT_H -#define GLSLextEXT_H - -static const int GLSLextEXTVersion = 100; -static const int GLSLextEXTRevision = 2; - -static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; -static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; -static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; -static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; -static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; -static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add"; -static const char* const E_SPV_EXT_shader_atomic_float16_add = "SPV_EXT_shader_atomic_float16_add"; -static const char* const E_SPV_EXT_shader_atomic_float_min_max = "SPV_EXT_shader_atomic_float_min_max"; -static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64"; -static const char* const E_SPV_EXT_shader_tile_image = "SPV_EXT_shader_tile_image"; -static const char* const E_SPV_EXT_mesh_shader = "SPV_EXT_mesh_shader"; -static const char* const E_SPV_ARM_cooperative_matrix_layouts = "SPV_ARM_cooperative_matrix_layouts"; - -#endif // #ifndef GLSLextEXT_H diff --git a/include/SPIRV/GLSL.ext.KHR.h b/include/SPIRV/GLSL.ext.KHR.h deleted file mode 100644 index 38d3b974..00000000 --- a/include/SPIRV/GLSL.ext.KHR.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -** Copyright (c) 2014-2020 The Khronos Group Inc. -** Copyright (C) 2022-2024 Arm Limited. -** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextKHR_H -#define GLSLextKHR_H - -static const int GLSLextKHRVersion = 100; -static const int GLSLextKHRRevision = 3; - -static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; -static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; -static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; -static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; -static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; -static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; -static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; -static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; -static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; -static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; -static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; -static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; -static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; -static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; -static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; -static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; -static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; -static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate"; -static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation"; -static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout"; -static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow"; -static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric"; -static const char* const E_SPV_KHR_quad_control = "SPV_KHR_quad_control"; -static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests"; -static const char* const E_SPV_KHR_ray_tracing_position_fetch = "SPV_KHR_ray_tracing_position_fetch"; -static const char* const E_SPV_KHR_cooperative_matrix = "SPV_KHR_cooperative_matrix"; -static const char* const E_SPV_KHR_maximal_reconvergence = "SPV_KHR_maximal_reconvergence"; -static const char* const E_SPV_KHR_subgroup_rotate = "SPV_KHR_subgroup_rotate"; -static const char* const E_SPV_KHR_expect_assume = "SPV_KHR_expect_assume"; -static const char* const E_SPV_EXT_replicated_composites = "SPV_EXT_replicated_composites"; -static const char* const E_SPV_KHR_relaxed_extended_instruction = "SPV_KHR_relaxed_extended_instruction"; - -#endif // #ifndef GLSLextKHR_H diff --git a/include/SPIRV/GLSL.ext.NV.h b/include/SPIRV/GLSL.ext.NV.h deleted file mode 100644 index d449c45b..00000000 --- a/include/SPIRV/GLSL.ext.NV.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -** Copyright (c) 2014-2017 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextNV_H -#define GLSLextNV_H - -enum BuiltIn; -enum Decoration; -enum Op; -enum Capability; - -static const int GLSLextNVVersion = 100; -static const int GLSLextNVRevision = 11; - -//SPV_NV_sample_mask_override_coverage -const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; - -//SPV_NV_geometry_shader_passthrough -const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; - -//SPV_NV_viewport_array2 -const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; -const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; - -//SPV_NV_stereo_view_rendering -const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; - -//SPV_NVX_multiview_per_view_attributes -const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; - -//SPV_NV_shader_subgroup_partitioned -const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; - -//SPV_NV_fragment_shader_barycentric -const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; - -//SPV_NV_compute_shader_derivatives -const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; - -//SPV_NV_shader_image_footprint -const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; - -//SPV_NV_mesh_shader -const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; - -//SPV_NV_raytracing -const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; - -//SPV_NV_ray_tracing_motion_blur -const char* const E_SPV_NV_ray_tracing_motion_blur = "SPV_NV_ray_tracing_motion_blur"; - -//SPV_NV_shading_rate -const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; - -//SPV_NV_cooperative_matrix -const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; - -//SPV_NV_shader_sm_builtins -const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; - -//SPV_NV_shader_execution_reorder -const char* const E_SPV_NV_shader_invocation_reorder = "SPV_NV_shader_invocation_reorder"; - -//SPV_NV_displacement_micromap -const char* const E_SPV_NV_displacement_micromap = "SPV_NV_displacement_micromap"; - -//SPV_NV_shader_atomic_fp16_vector -const char* const E_SPV_NV_shader_atomic_fp16_vector = "SPV_NV_shader_atomic_fp16_vector"; - -//SPV_NV_tensor_addressing -const char* const E_SPV_NV_tensor_addressing = "SPV_NV_tensor_addressing"; - -//SPV_NV_cooperative_matrix2 -const char* const E_SPV_NV_cooperative_matrix2 = "SPV_NV_cooperative_matrix2"; - -#endif // #ifndef GLSLextNV_H diff --git a/include/SPIRV/GLSL.ext.QCOM.h b/include/SPIRV/GLSL.ext.QCOM.h deleted file mode 100644 index b52990f0..00000000 --- a/include/SPIRV/GLSL.ext.QCOM.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -** Copyright (c) 2021 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextQCOM_H -#define GLSLextQCOM_H - -enum BuiltIn; -enum Decoration; -enum Op; -enum Capability; - -static const int GLSLextQCOMVersion = 100; -static const int GLSLextQCOMRevision = 1; - -//SPV_QCOM_image_processing -const char* const E_SPV_QCOM_image_processing = "SPV_QCOM_image_processing"; -//SPV_QCOM_image_processing2 -const char* const E_SPV_QCOM_image_processing2 = "SPV_QCOM_image_processing2"; - -#endif // #ifndef GLSLextQCOM_H diff --git a/include/SPIRV/GLSL.std.450.h b/include/SPIRV/GLSL.std.450.h deleted file mode 100644 index 86d3da80..00000000 --- a/include/SPIRV/GLSL.std.450.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLstd450_H -#define GLSLstd450_H - -static const int GLSLstd450Version = 100; -static const int GLSLstd450Revision = 1; - -enum GLSLstd450 { - GLSLstd450Bad = 0, // Don't use - - GLSLstd450Round = 1, - GLSLstd450RoundEven = 2, - GLSLstd450Trunc = 3, - GLSLstd450FAbs = 4, - GLSLstd450SAbs = 5, - GLSLstd450FSign = 6, - GLSLstd450SSign = 7, - GLSLstd450Floor = 8, - GLSLstd450Ceil = 9, - GLSLstd450Fract = 10, - - GLSLstd450Radians = 11, - GLSLstd450Degrees = 12, - GLSLstd450Sin = 13, - GLSLstd450Cos = 14, - GLSLstd450Tan = 15, - GLSLstd450Asin = 16, - GLSLstd450Acos = 17, - GLSLstd450Atan = 18, - GLSLstd450Sinh = 19, - GLSLstd450Cosh = 20, - GLSLstd450Tanh = 21, - GLSLstd450Asinh = 22, - GLSLstd450Acosh = 23, - GLSLstd450Atanh = 24, - GLSLstd450Atan2 = 25, - - GLSLstd450Pow = 26, - GLSLstd450Exp = 27, - GLSLstd450Log = 28, - GLSLstd450Exp2 = 29, - GLSLstd450Log2 = 30, - GLSLstd450Sqrt = 31, - GLSLstd450InverseSqrt = 32, - - GLSLstd450Determinant = 33, - GLSLstd450MatrixInverse = 34, - - GLSLstd450Modf = 35, // second operand needs an OpVariable to write to - GLSLstd450ModfStruct = 36, // no OpVariable operand - GLSLstd450FMin = 37, - GLSLstd450UMin = 38, - GLSLstd450SMin = 39, - GLSLstd450FMax = 40, - GLSLstd450UMax = 41, - GLSLstd450SMax = 42, - GLSLstd450FClamp = 43, - GLSLstd450UClamp = 44, - GLSLstd450SClamp = 45, - GLSLstd450FMix = 46, - GLSLstd450IMix = 47, // Reserved - GLSLstd450Step = 48, - GLSLstd450SmoothStep = 49, - - GLSLstd450Fma = 50, - GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to - GLSLstd450FrexpStruct = 52, // no OpVariable operand - GLSLstd450Ldexp = 53, - - GLSLstd450PackSnorm4x8 = 54, - GLSLstd450PackUnorm4x8 = 55, - GLSLstd450PackSnorm2x16 = 56, - GLSLstd450PackUnorm2x16 = 57, - GLSLstd450PackHalf2x16 = 58, - GLSLstd450PackDouble2x32 = 59, - GLSLstd450UnpackSnorm2x16 = 60, - GLSLstd450UnpackUnorm2x16 = 61, - GLSLstd450UnpackHalf2x16 = 62, - GLSLstd450UnpackSnorm4x8 = 63, - GLSLstd450UnpackUnorm4x8 = 64, - GLSLstd450UnpackDouble2x32 = 65, - - GLSLstd450Length = 66, - GLSLstd450Distance = 67, - GLSLstd450Cross = 68, - GLSLstd450Normalize = 69, - GLSLstd450FaceForward = 70, - GLSLstd450Reflect = 71, - GLSLstd450Refract = 72, - - GLSLstd450FindILsb = 73, - GLSLstd450FindSMsb = 74, - GLSLstd450FindUMsb = 75, - - GLSLstd450InterpolateAtCentroid = 76, - GLSLstd450InterpolateAtSample = 77, - GLSLstd450InterpolateAtOffset = 78, - - GLSLstd450NMin = 79, - GLSLstd450NMax = 80, - GLSLstd450NClamp = 81, - - GLSLstd450Count -}; - -#endif // #ifndef GLSLstd450_H diff --git a/include/SPIRV/GlslangToSpv.cpp b/include/SPIRV/GlslangToSpv.cpp deleted file mode 100644 index 382a6902..00000000 --- a/include/SPIRV/GlslangToSpv.cpp +++ /dev/null @@ -1,10434 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2015-2020 Google, Inc. -// Copyright (C) 2017, 2022-2024 Arm Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Visit the nodes in the glslang intermediate tree representation to -// translate them to SPIR-V. -// - -#include "spirv.hpp" -#include "GlslangToSpv.h" -#include "SpvBuilder.h" -#include "SpvTools.h" -namespace spv { - #include "GLSL.std.450.h" - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "GLSL.ext.QCOM.h" - #include "NonSemanticDebugPrintf.h" -} - -// Glslang includes -#include "../glslang/MachineIndependent/localintermediate.h" -#include "../glslang/MachineIndependent/SymbolTable.h" -#include "../glslang/Include/Common.h" - -// Build-time generated includes -#include "glslang/build_info.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - -namespace { -class SpecConstantOpModeGuard { -public: - SpecConstantOpModeGuard(spv::Builder* builder) - : builder_(builder) { - previous_flag_ = builder->isInSpecConstCodeGenMode(); - } - ~SpecConstantOpModeGuard() { - previous_flag_ ? builder_->setToSpecConstCodeGenMode() - : builder_->setToNormalCodeGenMode(); - } - void turnOnSpecConstantOpMode() { - builder_->setToSpecConstCodeGenMode(); - } - -private: - spv::Builder* builder_; - bool previous_flag_; -}; - -struct OpDecorations { - public: - OpDecorations(spv::Decoration precision, spv::Decoration noContraction, spv::Decoration nonUniform) : - precision(precision) - , - noContraction(noContraction), - nonUniform(nonUniform) - { } - - spv::Decoration precision; - - void addNoContraction(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, noContraction); } - void addNonUniform(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, nonUniform); } - protected: - spv::Decoration noContraction; - spv::Decoration nonUniform; -}; - -} // namespace - -// -// The main holder of information for translating glslang to SPIR-V. -// -// Derives from the AST walking base class. -// -class TGlslangToSpvTraverser : public glslang::TIntermTraverser { -public: - TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate*, spv::SpvBuildLogger* logger, - glslang::SpvOptions& options); - virtual ~TGlslangToSpvTraverser() { } - - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*); - bool visitBinary(glslang::TVisit, glslang::TIntermBinary*); - void visitConstantUnion(glslang::TIntermConstantUnion*); - bool visitSelection(glslang::TVisit, glslang::TIntermSelection*); - bool visitSwitch(glslang::TVisit, glslang::TIntermSwitch*); - void visitSymbol(glslang::TIntermSymbol* symbol); - bool visitUnary(glslang::TVisit, glslang::TIntermUnary*); - bool visitLoop(glslang::TVisit, glslang::TIntermLoop*); - bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*); - - void finishSpv(bool compileOnly); - void dumpSpv(std::vector& out); - -protected: - TGlslangToSpvTraverser(TGlslangToSpvTraverser&); - TGlslangToSpvTraverser& operator=(TGlslangToSpvTraverser&); - - spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateNonUniformDecoration(const spv::Builder::AccessChain::CoherentFlags& coherentFlags); - spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type); - spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); - spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); - spv::Scope TranslateMemoryScope(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); - spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration); - spv::ImageFormat TranslateImageFormat(const glslang::TType& type); - spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const; - spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const; - spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector& operands) const; - spv::StorageClass TranslateStorageClass(const glslang::TType&); - void TranslateLiterals(const glslang::TVector&, std::vector&) const; - void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType); - spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType); - spv::Id getSampledType(const glslang::TSampler&); - spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&); - spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult); - void convertSwizzle(const glslang::TIntermAggregate&, std::vector& swizzle); - spv::Id convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly = false); - spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&, - bool lastBufferBlockMember, bool forwardReferenceOnly = false); - void applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional member); - bool filterMember(const glslang::TType& member); - spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, - glslang::TLayoutPacking, const glslang::TQualifier&); - spv::LinkageType convertGlslangLinkageToSpv(glslang::TLinkType glslangLinkType); - void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, - const glslang::TQualifier&, spv::Id, const std::vector& spvMembers); - spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim, bool allowZero = false, bool boolType = false); - spv::Id accessChainLoad(const glslang::TType& type); - void accessChainStore(const glslang::TType& type, spv::Id rvalue); - void multiTypeStore(const glslang::TType&, spv::Id rValue); - spv::Id convertLoadedBoolInUniformToUint(const glslang::TType& type, spv::Id nominalTypeId, spv::Id loadedId); - glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; - int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, - int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember); - - bool isShaderEntryPoint(const glslang::TIntermAggregate* node); - bool writableParam(glslang::TStorageQualifier) const; - bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam); - void makeFunctions(const glslang::TIntermSequence&); - void makeGlobalInitializers(const glslang::TIntermSequence&); - void collectRayTracingLinkerObjects(); - void visitFunctions(const glslang::TIntermSequence&); - void handleFunctionEntry(const glslang::TIntermAggregate* node); - void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, - spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); - void translateArguments(glslang::TIntermUnary& node, std::vector& arguments); - spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); - spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); - - spv::Id createBinaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right, - glslang::TBasicType typeProxy, bool reduceComparison = true); - spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right); - spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy, - const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags, - const glslang::TType &opType); - spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy); - spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand, - glslang::TBasicType resultBasicType, glslang::TBasicType operandBasicType); - spv::Id createIntWidthConversion(spv::Id operand, int vectorSize, spv::Id destType, - glslang::TBasicType resultBasicType, glslang::TBasicType operandBasicType); - spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); - spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy, - const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags, - const glslang::TType &opType); - spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, - glslang::TBasicType typeProxy); - spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, - spv::Id typeId, std::vector& operands); - spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, - glslang::TBasicType typeProxy); - spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); - spv::Id getSymbolId(const glslang::TIntermSymbol* node); - void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier); - bool hasQCOMImageProceessingDecoration(spv::Id id, spv::Decoration decor); - void addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor); - void addImageProcessing2QCOMDecoration(spv::Id id, bool isForGather); - spv::Id createSpvConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, - int& nextConst, bool specConstant); - bool isTrivialLeaf(const glslang::TIntermTyped* node); - bool isTrivial(const glslang::TIntermTyped* node); - spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); - spv::Id getExtBuiltins(const char* name); - std::pair getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&); - spv::Id translateForcedType(spv::Id object); - spv::Id createCompositeConstruct(spv::Id typeId, std::vector constituents); - - glslang::SpvOptions& options; - spv::Function* shaderEntry; - spv::Function* currentFunction; - spv::Instruction* entryPoint; - int sequenceDepth; - - spv::SpvBuildLogger* logger; - - // There is a 1:1 mapping between a spv builder and a module; this is thread safe - spv::Builder builder; - bool inEntryPoint; - bool entryPointTerminated; - bool linkageOnly; // true when visiting the set of objects in the AST present only for - // establishing interface, whether or not they were statically used - std::set iOSet; // all input/output variables from either static use or declaration of interface - const glslang::TIntermediate* glslangIntermediate; - bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp - spv::Id stdBuiltins; - spv::Id nonSemanticDebugPrintf; - std::unordered_map extBuiltinMap; - - std::unordered_map symbolValues; - std::unordered_map builtInVariableIds; - std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, - // rather than a pointer - std::unordered_map functionMap; - std::unordered_map structMap[glslang::ElpCount][glslang::ElmCount]; - // for mapping glslang block indices to spv indices (e.g., due to hidden members): - std::unordered_map> memberRemapper; - // for mapping glslang symbol struct to symbol Id - std::unordered_map glslangTypeToIdMap; - std::stack breakForLoop; // false means break for switch - std::unordered_map counterOriginator; - // Map pointee types for EbtReference to their forward pointers - std::map forwardPointers; - // Type forcing, for when SPIR-V wants a different type than the AST, - // requiring local translation to and from SPIR-V type on every access. - // Maps AST-required-type-id> - std::unordered_map forceType; - // Used by Task shader while generating opearnds for OpEmitMeshTasksEXT - spv::Id taskPayloadID; - // Used later for generating OpTraceKHR/OpExecuteCallableKHR/OpHitObjectRecordHit*/OpHitObjectGetShaderBindingTableData - std::unordered_map locationToSymbol[4]; - std::unordered_map > idToQCOMDecorations; -}; - -// -// Helper functions for translating glslang representations to SPIR-V enumerants. -// - -// Translate glslang profile to SPIR-V source language. -spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile) -{ - switch (source) { - case glslang::EShSourceGlsl: - switch (profile) { - case ENoProfile: - case ECoreProfile: - case ECompatibilityProfile: - return spv::SourceLanguageGLSL; - case EEsProfile: - return spv::SourceLanguageESSL; - default: - return spv::SourceLanguageUnknown; - } - case glslang::EShSourceHlsl: - return spv::SourceLanguageHLSL; - default: - return spv::SourceLanguageUnknown; - } -} - -// Translate glslang language (stage) to SPIR-V execution model. -spv::ExecutionModel TranslateExecutionModel(EShLanguage stage, bool isMeshShaderEXT = false) -{ - switch (stage) { - case EShLangVertex: return spv::ExecutionModelVertex; - case EShLangFragment: return spv::ExecutionModelFragment; - case EShLangCompute: return spv::ExecutionModelGLCompute; - case EShLangTessControl: return spv::ExecutionModelTessellationControl; - case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation; - case EShLangGeometry: return spv::ExecutionModelGeometry; - case EShLangRayGen: return spv::ExecutionModelRayGenerationKHR; - case EShLangIntersect: return spv::ExecutionModelIntersectionKHR; - case EShLangAnyHit: return spv::ExecutionModelAnyHitKHR; - case EShLangClosestHit: return spv::ExecutionModelClosestHitKHR; - case EShLangMiss: return spv::ExecutionModelMissKHR; - case EShLangCallable: return spv::ExecutionModelCallableKHR; - case EShLangTask: return (isMeshShaderEXT)? spv::ExecutionModelTaskEXT : spv::ExecutionModelTaskNV; - case EShLangMesh: return (isMeshShaderEXT)? spv::ExecutionModelMeshEXT: spv::ExecutionModelMeshNV; - default: - assert(0); - return spv::ExecutionModelFragment; - } -} - -// Translate glslang sampler type to SPIR-V dimensionality. -spv::Dim TranslateDimensionality(const glslang::TSampler& sampler) -{ - switch (sampler.dim) { - case glslang::Esd1D: return spv::Dim1D; - case glslang::Esd2D: return spv::Dim2D; - case glslang::Esd3D: return spv::Dim3D; - case glslang::EsdCube: return spv::DimCube; - case glslang::EsdRect: return spv::DimRect; - case glslang::EsdBuffer: return spv::DimBuffer; - case glslang::EsdSubpass: return spv::DimSubpassData; - case glslang::EsdAttachmentEXT: return spv::DimTileImageDataEXT; - default: - assert(0); - return spv::Dim2D; - } -} - -// Translate glslang precision to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(glslang::TPrecisionQualifier glslangPrecision) -{ - switch (glslangPrecision) { - case glslang::EpqLow: return spv::DecorationRelaxedPrecision; - case glslang::EpqMedium: return spv::DecorationRelaxedPrecision; - default: - return spv::NoPrecision; - } -} - -// Translate glslang type to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type) -{ - return TranslatePrecisionDecoration(type.getQualifier().precision); -} - -// Translate glslang type to SPIR-V block decorations. -spv::Decoration TranslateBlockDecoration(const glslang::TStorageQualifier storage, bool useStorageBuffer) -{ - switch (storage) { - case glslang::EvqUniform: return spv::DecorationBlock; - case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; - case glslang::EvqVaryingIn: return spv::DecorationBlock; - case glslang::EvqVaryingOut: return spv::DecorationBlock; - case glslang::EvqShared: return spv::DecorationBlock; - case glslang::EvqPayload: return spv::DecorationBlock; - case glslang::EvqPayloadIn: return spv::DecorationBlock; - case glslang::EvqHitAttr: return spv::DecorationBlock; - case glslang::EvqCallableData: return spv::DecorationBlock; - case glslang::EvqCallableDataIn: return spv::DecorationBlock; - case glslang::EvqHitObjectAttrNV: return spv::DecorationBlock; - default: - assert(0); - break; - } - - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V memory decorations. -void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory, - bool useVulkanMemoryModel) -{ - if (!useVulkanMemoryModel) { - if (qualifier.isVolatile()) { - memory.push_back(spv::DecorationVolatile); - memory.push_back(spv::DecorationCoherent); - } else if (qualifier.isCoherent()) { - memory.push_back(spv::DecorationCoherent); - } - } - if (qualifier.isRestrict()) - memory.push_back(spv::DecorationRestrict); - if (qualifier.isReadOnly()) - memory.push_back(spv::DecorationNonWritable); - if (qualifier.isWriteOnly()) - memory.push_back(spv::DecorationNonReadable); -} - -// Translate glslang type to SPIR-V layout decorations. -spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout) -{ - if (type.isMatrix()) { - switch (matrixLayout) { - case glslang::ElmRowMajor: - return spv::DecorationRowMajor; - case glslang::ElmColumnMajor: - return spv::DecorationColMajor; - default: - // opaque layouts don't need a majorness - return spv::DecorationMax; - } - } else { - switch (type.getBasicType()) { - default: - return spv::DecorationMax; - break; - case glslang::EbtBlock: - switch (type.getQualifier().storage) { - case glslang::EvqShared: - case glslang::EvqUniform: - case glslang::EvqBuffer: - switch (type.getQualifier().layoutPacking) { - case glslang::ElpShared: return spv::DecorationGLSLShared; - case glslang::ElpPacked: return spv::DecorationGLSLPacked; - default: - return spv::DecorationMax; - } - case glslang::EvqVaryingIn: - case glslang::EvqVaryingOut: - if (type.getQualifier().isTaskMemory()) { - switch (type.getQualifier().layoutPacking) { - case glslang::ElpShared: return spv::DecorationGLSLShared; - case glslang::ElpPacked: return spv::DecorationGLSLPacked; - default: break; - } - } else { - assert(type.getQualifier().layoutPacking == glslang::ElpNone); - } - return spv::DecorationMax; - case glslang::EvqPayload: - case glslang::EvqPayloadIn: - case glslang::EvqHitAttr: - case glslang::EvqCallableData: - case glslang::EvqCallableDataIn: - case glslang::EvqHitObjectAttrNV: - return spv::DecorationMax; - default: - assert(0); - return spv::DecorationMax; - } - } - } -} - -// Translate glslang type to SPIR-V interpolation decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.smooth) - // Smooth decoration doesn't exist in SPIR-V 1.0 - return spv::DecorationMax; - else if (qualifier.isNonPerspective()) - return spv::DecorationNoPerspective; - else if (qualifier.flat) - return spv::DecorationFlat; - else if (qualifier.isExplicitInterpolation()) { - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::DecorationExplicitInterpAMD; - } - else - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V auxiliary storage decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.centroid) - return spv::DecorationCentroid; - else if (qualifier.patch) - return spv::DecorationPatch; - else if (qualifier.sample) { - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::DecorationSample; - } - - return spv::DecorationMax; -} - -// If glslang type is invariant, return SPIR-V invariant decoration. -spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.invariant) - return spv::DecorationInvariant; - else - return spv::DecorationMax; -} - -// If glslang type is noContraction, return SPIR-V NoContraction decoration. -spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.isNoContraction()) - return spv::DecorationNoContraction; - else - return spv::DecorationMax; -} - -// If glslang type is nonUniform, return SPIR-V NonUniform decoration. -spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.isNonUniform()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderNonUniformEXT); - return spv::DecorationNonUniformEXT; - } else - return spv::DecorationMax; -} - -// If lvalue flags contains nonUniform, return SPIR-V NonUniform decoration. -spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration( - const spv::Builder::AccessChain::CoherentFlags& coherentFlags) -{ - if (coherentFlags.isNonUniform()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderNonUniformEXT); - return spv::DecorationNonUniformEXT; - } else - return spv::DecorationMax; -} - -spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess( - const spv::Builder::AccessChain::CoherentFlags &coherentFlags) -{ - spv::MemoryAccessMask mask = spv::MemoryAccessMaskNone; - - if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage) - return mask; - - if (coherentFlags.isVolatile() || coherentFlags.anyCoherent()) { - mask = mask | spv::MemoryAccessMakePointerAvailableKHRMask | - spv::MemoryAccessMakePointerVisibleKHRMask; - } - - if (coherentFlags.nonprivate) { - mask = mask | spv::MemoryAccessNonPrivatePointerKHRMask; - } - if (coherentFlags.volatil) { - mask = mask | spv::MemoryAccessVolatileMask; - } - if (mask != spv::MemoryAccessMaskNone) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - return mask; -} - -spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands( - const spv::Builder::AccessChain::CoherentFlags &coherentFlags) -{ - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - - if (!glslangIntermediate->usingVulkanMemoryModel()) - return mask; - - if (coherentFlags.volatil || - coherentFlags.anyCoherent()) { - mask = mask | spv::ImageOperandsMakeTexelAvailableKHRMask | - spv::ImageOperandsMakeTexelVisibleKHRMask; - } - if (coherentFlags.nonprivate) { - mask = mask | spv::ImageOperandsNonPrivateTexelKHRMask; - } - if (coherentFlags.volatil) { - mask = mask | spv::ImageOperandsVolatileTexelKHRMask; - } - if (mask != spv::ImageOperandsMaskNone) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - return mask; -} - -spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCoherent(const glslang::TType& type) -{ - spv::Builder::AccessChain::CoherentFlags flags = {}; - flags.coherent = type.getQualifier().coherent; - flags.devicecoherent = type.getQualifier().devicecoherent; - flags.queuefamilycoherent = type.getQualifier().queuefamilycoherent; - // shared variables are implicitly workgroupcoherent in GLSL. - flags.workgroupcoherent = type.getQualifier().workgroupcoherent || - type.getQualifier().storage == glslang::EvqShared; - flags.subgroupcoherent = type.getQualifier().subgroupcoherent; - flags.shadercallcoherent = type.getQualifier().shadercallcoherent; - flags.volatil = type.getQualifier().volatil; - // *coherent variables are implicitly nonprivate in GLSL - flags.nonprivate = type.getQualifier().nonprivate || - flags.anyCoherent() || - flags.volatil; - flags.isImage = type.getBasicType() == glslang::EbtSampler; - flags.nonUniform = type.getQualifier().nonUniform; - return flags; -} - -spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope( - const spv::Builder::AccessChain::CoherentFlags &coherentFlags) -{ - spv::Scope scope = spv::ScopeMax; - - if (coherentFlags.volatil || coherentFlags.coherent) { - // coherent defaults to Device scope in the old model, QueueFamilyKHR scope in the new model - scope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice; - } else if (coherentFlags.devicecoherent) { - scope = spv::ScopeDevice; - } else if (coherentFlags.queuefamilycoherent) { - scope = spv::ScopeQueueFamilyKHR; - } else if (coherentFlags.workgroupcoherent) { - scope = spv::ScopeWorkgroup; - } else if (coherentFlags.subgroupcoherent) { - scope = spv::ScopeSubgroup; - } else if (coherentFlags.shadercallcoherent) { - scope = spv::ScopeShaderCallKHR; - } - if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - - return scope; -} - -// Translate a glslang built-in variable to a SPIR-V built in decoration. Also generate -// associated capabilities when required. For some built-in variables, a capability -// is generated only when using the variable in an executable instruction, but not when -// just declaring a struct member variable with it. This is true for PointSize, -// ClipDistance, and CullDistance. -spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, - bool memberDeclaration) -{ - switch (builtIn) { - case glslang::EbvPointSize: - // Defer adding the capability until the built-in is actually used. - if (! memberDeclaration) { - switch (glslangIntermediate->getStage()) { - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometryPointSize); - break; - case EShLangTessControl: - case EShLangTessEvaluation: - builder.addCapability(spv::CapabilityTessellationPointSize); - break; - default: - break; - } - } - return spv::BuiltInPointSize; - - case glslang::EbvPosition: return spv::BuiltInPosition; - case glslang::EbvVertexId: return spv::BuiltInVertexId; - case glslang::EbvInstanceId: return spv::BuiltInInstanceId; - case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex; - case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex; - - case glslang::EbvFragCoord: return spv::BuiltInFragCoord; - case glslang::EbvPointCoord: return spv::BuiltInPointCoord; - case glslang::EbvFace: return spv::BuiltInFrontFacing; - case glslang::EbvFragDepth: return spv::BuiltInFragDepth; - - case glslang::EbvNumWorkGroups: return spv::BuiltInNumWorkgroups; - case glslang::EbvWorkGroupSize: return spv::BuiltInWorkgroupSize; - case glslang::EbvWorkGroupId: return spv::BuiltInWorkgroupId; - case glslang::EbvLocalInvocationId: return spv::BuiltInLocalInvocationId; - case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex; - case glslang::EbvGlobalInvocationId: return spv::BuiltInGlobalInvocationId; - - // These *Distance capabilities logically belong here, but if the member is declared and - // then never used, consumers of SPIR-V prefer the capability not be declared. - // They are now generated when used, rather than here when declared. - // Potentially, the specification should be more clear what the minimum - // use needed is to trigger the capability. - // - case glslang::EbvClipDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityClipDistance); - return spv::BuiltInClipDistance; - - case glslang::EbvCullDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityCullDistance); - return spv::BuiltInCullDistance; - - case glslang::EbvViewportIndex: - if (glslangIntermediate->getStage() == EShLangGeometry || - glslangIntermediate->getStage() == EShLangFragment) { - builder.addCapability(spv::CapabilityMultiViewport); - } - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - if (builder.getSpvVersion() < spv::Spv_1_5) { - builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } - else - builder.addCapability(spv::CapabilityShaderViewportIndex); - } - return spv::BuiltInViewportIndex; - - case glslang::EbvSampleId: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSampleId; - - case glslang::EbvSamplePosition: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSamplePosition; - - case glslang::EbvSampleMask: - return spv::BuiltInSampleMask; - - case glslang::EbvLayer: - if (glslangIntermediate->getStage() == EShLangMesh) { - return spv::BuiltInLayer; - } - if (glslangIntermediate->getStage() == EShLangGeometry || - glslangIntermediate->getStage() == EShLangFragment) { - builder.addCapability(spv::CapabilityGeometry); - } - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - if (builder.getSpvVersion() < spv::Spv_1_5) { - builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } else - builder.addCapability(spv::CapabilityShaderLayer); - } - return spv::BuiltInLayer; - - case glslang::EbvBaseVertex: - builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseVertex; - - case glslang::EbvBaseInstance: - builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseInstance; - - case glslang::EbvDrawId: - builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInDrawIndex; - - case glslang::EbvPrimitiveId: - if (glslangIntermediate->getStage() == EShLangFragment) - builder.addCapability(spv::CapabilityGeometry); - return spv::BuiltInPrimitiveId; - - case glslang::EbvFragStencilRef: - builder.addExtension(spv::E_SPV_EXT_shader_stencil_export); - builder.addCapability(spv::CapabilityStencilExportEXT); - return spv::BuiltInFragStencilRefEXT; - - case glslang::EbvShadingRateKHR: - builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate); - builder.addCapability(spv::CapabilityFragmentShadingRateKHR); - return spv::BuiltInShadingRateKHR; - - case glslang::EbvPrimitiveShadingRateKHR: - builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate); - builder.addCapability(spv::CapabilityFragmentShadingRateKHR); - return spv::BuiltInPrimitiveShadingRateKHR; - - case glslang::EbvInvocationId: return spv::BuiltInInvocationId; - case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner; - case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter; - case glslang::EbvTessCoord: return spv::BuiltInTessCoord; - case glslang::EbvPatchVertices: return spv::BuiltInPatchVertices; - case glslang::EbvHelperInvocation: return spv::BuiltInHelperInvocation; - - case glslang::EbvSubGroupSize: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupSize; - - case glslang::EbvSubGroupInvocation: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLocalInvocationId; - - case glslang::EbvSubGroupEqMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupEqMask; - - case glslang::EbvSubGroupGeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGeMask; - - case glslang::EbvSubGroupGtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGtMask; - - case glslang::EbvSubGroupLeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLeMask; - - case glslang::EbvSubGroupLtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLtMask; - - case glslang::EbvNumSubgroups: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInNumSubgroups; - - case glslang::EbvSubgroupID: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupId; - - case glslang::EbvSubgroupSize2: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupSize; - - case glslang::EbvSubgroupInvocation2: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupLocalInvocationId; - - case glslang::EbvSubgroupEqMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupEqMask; - - case glslang::EbvSubgroupGeMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupGeMask; - - case glslang::EbvSubgroupGtMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupGtMask; - - case glslang::EbvSubgroupLeMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupLeMask; - - case glslang::EbvSubgroupLtMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupLtMask; - - case glslang::EbvBaryCoordNoPersp: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspAMD; - - case glslang::EbvBaryCoordNoPerspCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspCentroidAMD; - - case glslang::EbvBaryCoordNoPerspSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspSampleAMD; - - case glslang::EbvBaryCoordSmooth: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothAMD; - - case glslang::EbvBaryCoordSmoothCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothCentroidAMD; - - case glslang::EbvBaryCoordSmoothSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothSampleAMD; - - case glslang::EbvBaryCoordPullModel: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordPullModelAMD; - - case glslang::EbvDeviceIndex: - builder.addIncorporatedExtension(spv::E_SPV_KHR_device_group, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDeviceGroup); - return spv::BuiltInDeviceIndex; - - case glslang::EbvViewIndex: - builder.addIncorporatedExtension(spv::E_SPV_KHR_multiview, spv::Spv_1_3); - builder.addCapability(spv::CapabilityMultiView); - return spv::BuiltInViewIndex; - - case glslang::EbvFragSizeEXT: - builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density); - builder.addCapability(spv::CapabilityFragmentDensityEXT); - return spv::BuiltInFragSizeEXT; - - case glslang::EbvFragInvocationCountEXT: - builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density); - builder.addCapability(spv::CapabilityFragmentDensityEXT); - return spv::BuiltInFragInvocationCountEXT; - - case glslang::EbvViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_viewport_array2); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - } - return spv::BuiltInViewportMaskNV; - case glslang::EbvSecondaryPositionNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryPositionNV; - case glslang::EbvSecondaryViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryViewportMaskNV; - case glslang::EbvPositionPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInPositionPerViewNV; - case glslang::EbvViewportMaskPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInViewportMaskPerViewNV; - case glslang::EbvFragFullyCoveredNV: - builder.addExtension(spv::E_SPV_EXT_fragment_fully_covered); - builder.addCapability(spv::CapabilityFragmentFullyCoveredEXT); - return spv::BuiltInFullyCoveredEXT; - case glslang::EbvFragmentSizeNV: - builder.addExtension(spv::E_SPV_NV_shading_rate); - builder.addCapability(spv::CapabilityShadingRateNV); - return spv::BuiltInFragmentSizeNV; - case glslang::EbvInvocationsPerPixelNV: - builder.addExtension(spv::E_SPV_NV_shading_rate); - builder.addCapability(spv::CapabilityShadingRateNV); - return spv::BuiltInInvocationsPerPixelNV; - - // ray tracing - case glslang::EbvLaunchId: - return spv::BuiltInLaunchIdKHR; - case glslang::EbvLaunchSize: - return spv::BuiltInLaunchSizeKHR; - case glslang::EbvWorldRayOrigin: - return spv::BuiltInWorldRayOriginKHR; - case glslang::EbvWorldRayDirection: - return spv::BuiltInWorldRayDirectionKHR; - case glslang::EbvObjectRayOrigin: - return spv::BuiltInObjectRayOriginKHR; - case glslang::EbvObjectRayDirection: - return spv::BuiltInObjectRayDirectionKHR; - case glslang::EbvRayTmin: - return spv::BuiltInRayTminKHR; - case glslang::EbvRayTmax: - return spv::BuiltInRayTmaxKHR; - case glslang::EbvCullMask: - return spv::BuiltInCullMaskKHR; - case glslang::EbvPositionFetch: - return spv::BuiltInHitTriangleVertexPositionsKHR; - case glslang::EbvInstanceCustomIndex: - return spv::BuiltInInstanceCustomIndexKHR; - case glslang::EbvHitKind: - return spv::BuiltInHitKindKHR; - case glslang::EbvObjectToWorld: - case glslang::EbvObjectToWorld3x4: - return spv::BuiltInObjectToWorldKHR; - case glslang::EbvWorldToObject: - case glslang::EbvWorldToObject3x4: - return spv::BuiltInWorldToObjectKHR; - case glslang::EbvIncomingRayFlags: - return spv::BuiltInIncomingRayFlagsKHR; - case glslang::EbvGeometryIndex: - return spv::BuiltInRayGeometryIndexKHR; - case glslang::EbvCurrentRayTimeNV: - builder.addExtension(spv::E_SPV_NV_ray_tracing_motion_blur); - builder.addCapability(spv::CapabilityRayTracingMotionBlurNV); - return spv::BuiltInCurrentRayTimeNV; - case glslang::EbvMicroTrianglePositionNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitMicroTriangleVertexPositionsNV; - case glslang::EbvMicroTriangleBaryNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitMicroTriangleVertexBarycentricsNV; - case glslang::EbvHitKindFrontFacingMicroTriangleNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitKindFrontFacingMicroTriangleNV; - case glslang::EbvHitKindBackFacingMicroTriangleNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitKindBackFacingMicroTriangleNV; - - // barycentrics - case glslang::EbvBaryCoordNV: - builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricNV); - return spv::BuiltInBaryCoordNV; - case glslang::EbvBaryCoordNoPerspNV: - builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricNV); - return spv::BuiltInBaryCoordNoPerspNV; - - case glslang::EbvBaryCoordEXT: - builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricKHR); - return spv::BuiltInBaryCoordKHR; - case glslang::EbvBaryCoordNoPerspEXT: - builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricKHR); - return spv::BuiltInBaryCoordNoPerspKHR; - - // mesh shaders - case glslang::EbvTaskCountNV: - return spv::BuiltInTaskCountNV; - case glslang::EbvPrimitiveCountNV: - return spv::BuiltInPrimitiveCountNV; - case glslang::EbvPrimitiveIndicesNV: - return spv::BuiltInPrimitiveIndicesNV; - case glslang::EbvClipDistancePerViewNV: - return spv::BuiltInClipDistancePerViewNV; - case glslang::EbvCullDistancePerViewNV: - return spv::BuiltInCullDistancePerViewNV; - case glslang::EbvLayerPerViewNV: - return spv::BuiltInLayerPerViewNV; - case glslang::EbvMeshViewCountNV: - return spv::BuiltInMeshViewCountNV; - case glslang::EbvMeshViewIndicesNV: - return spv::BuiltInMeshViewIndicesNV; - - // SPV_EXT_mesh_shader - case glslang::EbvPrimitivePointIndicesEXT: - return spv::BuiltInPrimitivePointIndicesEXT; - case glslang::EbvPrimitiveLineIndicesEXT: - return spv::BuiltInPrimitiveLineIndicesEXT; - case glslang::EbvPrimitiveTriangleIndicesEXT: - return spv::BuiltInPrimitiveTriangleIndicesEXT; - case glslang::EbvCullPrimitiveEXT: - return spv::BuiltInCullPrimitiveEXT; - - // sm builtins - case glslang::EbvWarpsPerSM: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInWarpsPerSMNV; - case glslang::EbvSMCount: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInSMCountNV; - case glslang::EbvWarpID: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInWarpIDNV; - case glslang::EbvSMID: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInSMIDNV; - - // ARM builtins - case glslang::EbvCoreCountARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInCoreCountARM; - case glslang::EbvCoreIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInCoreIDARM; - case glslang::EbvCoreMaxIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInCoreMaxIDARM; - case glslang::EbvWarpIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInWarpIDARM; - case glslang::EbvWarpMaxIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInWarpMaxIDARM; - - default: - return spv::BuiltInMax; - } -} - -// Translate glslang image layout format to SPIR-V image format. -spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type) -{ - assert(type.getBasicType() == glslang::EbtSampler); - - // Check for capabilities - switch (type.getQualifier().getFormat()) { - case glslang::ElfRg32f: - case glslang::ElfRg16f: - case glslang::ElfR11fG11fB10f: - case glslang::ElfR16f: - case glslang::ElfRgba16: - case glslang::ElfRgb10A2: - case glslang::ElfRg16: - case glslang::ElfRg8: - case glslang::ElfR16: - case glslang::ElfR8: - case glslang::ElfRgba16Snorm: - case glslang::ElfRg16Snorm: - case glslang::ElfRg8Snorm: - case glslang::ElfR16Snorm: - case glslang::ElfR8Snorm: - - case glslang::ElfRg32i: - case glslang::ElfRg16i: - case glslang::ElfRg8i: - case glslang::ElfR16i: - case glslang::ElfR8i: - - case glslang::ElfRgb10a2ui: - case glslang::ElfRg32ui: - case glslang::ElfRg16ui: - case glslang::ElfRg8ui: - case glslang::ElfR16ui: - case glslang::ElfR8ui: - builder.addCapability(spv::CapabilityStorageImageExtendedFormats); - break; - - case glslang::ElfR64ui: - case glslang::ElfR64i: - builder.addExtension(spv::E_SPV_EXT_shader_image_int64); - builder.addCapability(spv::CapabilityInt64ImageEXT); - break; - default: - break; - } - - // do the translation - switch (type.getQualifier().getFormat()) { - case glslang::ElfNone: return spv::ImageFormatUnknown; - case glslang::ElfRgba32f: return spv::ImageFormatRgba32f; - case glslang::ElfRgba16f: return spv::ImageFormatRgba16f; - case glslang::ElfR32f: return spv::ImageFormatR32f; - case glslang::ElfRgba8: return spv::ImageFormatRgba8; - case glslang::ElfRgba8Snorm: return spv::ImageFormatRgba8Snorm; - case glslang::ElfRg32f: return spv::ImageFormatRg32f; - case glslang::ElfRg16f: return spv::ImageFormatRg16f; - case glslang::ElfR11fG11fB10f: return spv::ImageFormatR11fG11fB10f; - case glslang::ElfR16f: return spv::ImageFormatR16f; - case glslang::ElfRgba16: return spv::ImageFormatRgba16; - case glslang::ElfRgb10A2: return spv::ImageFormatRgb10A2; - case glslang::ElfRg16: return spv::ImageFormatRg16; - case glslang::ElfRg8: return spv::ImageFormatRg8; - case glslang::ElfR16: return spv::ImageFormatR16; - case glslang::ElfR8: return spv::ImageFormatR8; - case glslang::ElfRgba16Snorm: return spv::ImageFormatRgba16Snorm; - case glslang::ElfRg16Snorm: return spv::ImageFormatRg16Snorm; - case glslang::ElfRg8Snorm: return spv::ImageFormatRg8Snorm; - case glslang::ElfR16Snorm: return spv::ImageFormatR16Snorm; - case glslang::ElfR8Snorm: return spv::ImageFormatR8Snorm; - case glslang::ElfRgba32i: return spv::ImageFormatRgba32i; - case glslang::ElfRgba16i: return spv::ImageFormatRgba16i; - case glslang::ElfRgba8i: return spv::ImageFormatRgba8i; - case glslang::ElfR32i: return spv::ImageFormatR32i; - case glslang::ElfRg32i: return spv::ImageFormatRg32i; - case glslang::ElfRg16i: return spv::ImageFormatRg16i; - case glslang::ElfRg8i: return spv::ImageFormatRg8i; - case glslang::ElfR16i: return spv::ImageFormatR16i; - case glslang::ElfR8i: return spv::ImageFormatR8i; - case glslang::ElfRgba32ui: return spv::ImageFormatRgba32ui; - case glslang::ElfRgba16ui: return spv::ImageFormatRgba16ui; - case glslang::ElfRgba8ui: return spv::ImageFormatRgba8ui; - case glslang::ElfR32ui: return spv::ImageFormatR32ui; - case glslang::ElfRg32ui: return spv::ImageFormatRg32ui; - case glslang::ElfRg16ui: return spv::ImageFormatRg16ui; - case glslang::ElfRgb10a2ui: return spv::ImageFormatRgb10a2ui; - case glslang::ElfRg8ui: return spv::ImageFormatRg8ui; - case glslang::ElfR16ui: return spv::ImageFormatR16ui; - case glslang::ElfR8ui: return spv::ImageFormatR8ui; - case glslang::ElfR64ui: return spv::ImageFormatR64ui; - case glslang::ElfR64i: return spv::ImageFormatR64i; - default: return spv::ImageFormatMax; - } -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl( - const glslang::TIntermSelection& selectionNode) const -{ - if (selectionNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (selectionNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) - const -{ - if (switchNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (switchNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -// return a non-0 dependency if the dependency argument must be set -spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode, - std::vector& operands) const -{ - spv::LoopControlMask control = spv::LoopControlMaskNone; - - if (loopNode.getDontUnroll()) - control = control | spv::LoopControlDontUnrollMask; - if (loopNode.getUnroll()) - control = control | spv::LoopControlUnrollMask; - if (unsigned(loopNode.getLoopDependency()) == glslang::TIntermLoop::dependencyInfinite) - control = control | spv::LoopControlDependencyInfiniteMask; - else if (loopNode.getLoopDependency() > 0) { - control = control | spv::LoopControlDependencyLengthMask; - operands.push_back((unsigned int)loopNode.getLoopDependency()); - } - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { - if (loopNode.getMinIterations() > 0) { - control = control | spv::LoopControlMinIterationsMask; - operands.push_back(loopNode.getMinIterations()); - } - if (loopNode.getMaxIterations() < glslang::TIntermLoop::iterationsInfinite) { - control = control | spv::LoopControlMaxIterationsMask; - operands.push_back(loopNode.getMaxIterations()); - } - if (loopNode.getIterationMultiple() > 1) { - control = control | spv::LoopControlIterationMultipleMask; - operands.push_back(loopNode.getIterationMultiple()); - } - if (loopNode.getPeelCount() > 0) { - control = control | spv::LoopControlPeelCountMask; - operands.push_back(loopNode.getPeelCount()); - } - if (loopNode.getPartialCount() > 0) { - control = control | spv::LoopControlPartialCountMask; - operands.push_back(loopNode.getPartialCount()); - } - } - - return control; -} - -// Translate glslang type to SPIR-V storage class. -spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type) -{ - if (type.getBasicType() == glslang::EbtRayQuery || type.getBasicType() == glslang::EbtHitObjectNV) - return spv::StorageClassPrivate; - if (type.getQualifier().isSpirvByReference()) { - if (type.getQualifier().isParamInput() || type.getQualifier().isParamOutput()) - return spv::StorageClassFunction; - } - if (type.getQualifier().isPipeInput()) - return spv::StorageClassInput; - if (type.getQualifier().isPipeOutput()) - return spv::StorageClassOutput; - if (type.getQualifier().storage == glslang::EvqTileImageEXT || type.isAttachmentEXT()) { - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.addCapability(spv::CapabilityTileImageColorReadAccessEXT); - return spv::StorageClassTileImageEXT; - } - - if (glslangIntermediate->getSource() != glslang::EShSourceHlsl || - type.getQualifier().storage == glslang::EvqUniform) { - if (type.isAtomic()) - return spv::StorageClassAtomicCounter; - if (type.containsOpaque() && !glslangIntermediate->getBindlessMode()) - return spv::StorageClassUniformConstant; - } - - if (type.getQualifier().isUniformOrBuffer() && - type.getQualifier().isShaderRecord()) { - return spv::StorageClassShaderRecordBufferKHR; - } - - if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_storage_buffer_storage_class, spv::Spv_1_3); - return spv::StorageClassStorageBuffer; - } - - if (type.getQualifier().isUniformOrBuffer()) { - if (type.getQualifier().isPushConstant()) - return spv::StorageClassPushConstant; - if (type.getBasicType() == glslang::EbtBlock) - return spv::StorageClassUniform; - return spv::StorageClassUniformConstant; - } - - if (type.getQualifier().storage == glslang::EvqShared && type.getBasicType() == glslang::EbtBlock) { - builder.addExtension(spv::E_SPV_KHR_workgroup_memory_explicit_layout); - builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR); - return spv::StorageClassWorkgroup; - } - - switch (type.getQualifier().storage) { - case glslang::EvqGlobal: return spv::StorageClassPrivate; - case glslang::EvqConstReadOnly: return spv::StorageClassFunction; - case glslang::EvqTemporary: return spv::StorageClassFunction; - case glslang::EvqShared: return spv::StorageClassWorkgroup; - case glslang::EvqPayload: return spv::StorageClassRayPayloadKHR; - case glslang::EvqPayloadIn: return spv::StorageClassIncomingRayPayloadKHR; - case glslang::EvqHitAttr: return spv::StorageClassHitAttributeKHR; - case glslang::EvqCallableData: return spv::StorageClassCallableDataKHR; - case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR; - case glslang::EvqtaskPayloadSharedEXT : return spv::StorageClassTaskPayloadWorkgroupEXT; - case glslang::EvqHitObjectAttrNV: return spv::StorageClassHitObjectAttributeNV; - case glslang::EvqSpirvStorageClass: return static_cast(type.getQualifier().spirvStorageClass); - default: - assert(0); - break; - } - - return spv::StorageClassFunction; -} - -// Translate glslang constants to SPIR-V literals -void TGlslangToSpvTraverser::TranslateLiterals(const glslang::TVector& constants, - std::vector& literals) const -{ - for (auto constant : constants) { - if (constant->getBasicType() == glslang::EbtFloat) { - float floatValue = static_cast(constant->getConstArray()[0].getDConst()); - unsigned literal; - static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)"); - memcpy(&literal, &floatValue, sizeof(literal)); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtInt) { - unsigned literal = constant->getConstArray()[0].getIConst(); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtUint) { - unsigned literal = constant->getConstArray()[0].getUConst(); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtBool) { - unsigned literal = constant->getConstArray()[0].getBConst(); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtString) { - auto str = constant->getConstArray()[0].getSConst()->c_str(); - unsigned literal = 0; - char* literalPtr = reinterpret_cast(&literal); - unsigned charCount = 0; - char ch = 0; - do { - ch = *(str++); - *(literalPtr++) = ch; - ++charCount; - if (charCount == 4) { - literals.push_back(literal); - literalPtr = reinterpret_cast(&literal); - charCount = 0; - } - } while (ch != 0); - - // Partial literal is padded with 0 - if (charCount > 0) { - for (; charCount < 4; ++charCount) - *(literalPtr++) = 0; - literals.push_back(literal); - } - } else - assert(0); // Unexpected type - } -} - -// Add capabilities pertaining to how an array is indexed. -void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType, - const glslang::TType& indexType) -{ - if (indexType.getQualifier().isNonUniform()) { - // deal with an asserted non-uniform index - // SPV_EXT_descriptor_indexing already added in TranslateNonUniformDecoration - if (baseType.getBasicType() == glslang::EbtSampler) { - if (baseType.getQualifier().hasAttachment()) - builder.addCapability(spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT); - else if (baseType.isImage() && baseType.getSampler().isBuffer()) - builder.addCapability(spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT); - else if (baseType.isTexture() && baseType.getSampler().isBuffer()) - builder.addCapability(spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT); - else if (baseType.isImage()) - builder.addCapability(spv::CapabilityStorageImageArrayNonUniformIndexingEXT); - else if (baseType.isTexture()) - builder.addCapability(spv::CapabilitySampledImageArrayNonUniformIndexingEXT); - } else if (baseType.getBasicType() == glslang::EbtBlock) { - if (baseType.getQualifier().storage == glslang::EvqBuffer) - builder.addCapability(spv::CapabilityStorageBufferArrayNonUniformIndexingEXT); - else if (baseType.getQualifier().storage == glslang::EvqUniform) - builder.addCapability(spv::CapabilityUniformBufferArrayNonUniformIndexingEXT); - } - } else { - // assume a dynamically uniform index - if (baseType.getBasicType() == glslang::EbtSampler) { - if (baseType.getQualifier().hasAttachment()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityInputAttachmentArrayDynamicIndexingEXT); - } else if (baseType.isImage() && baseType.getSampler().isBuffer()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT); - } else if (baseType.isTexture() && baseType.getSampler().isBuffer()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT); - } - } - } -} - -// Return whether or not the given type is something that should be tied to a -// descriptor set. -bool IsDescriptorResource(const glslang::TType& type) -{ - // uniform and buffer blocks are included, unless it is a push_constant - if (type.getBasicType() == glslang::EbtBlock) - return type.getQualifier().isUniformOrBuffer() && - ! type.getQualifier().isShaderRecord() && - ! type.getQualifier().isPushConstant(); - - // non block... - // basically samplerXXX/subpass/sampler/texture are all included - // if they are the global-scope-class, not the function parameter - // (or local, if they ever exist) class. - if (type.getBasicType() == glslang::EbtSampler || - type.getBasicType() == glslang::EbtAccStruct) - return type.getQualifier().isUniformOrBuffer(); - - // None of the above. - return false; -} - -void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent) -{ - if (child.layoutMatrix == glslang::ElmNone) - child.layoutMatrix = parent.layoutMatrix; - - if (parent.invariant) - child.invariant = true; - if (parent.flat) - child.flat = true; - if (parent.centroid) - child.centroid = true; - if (parent.nopersp) - child.nopersp = true; - if (parent.explicitInterp) - child.explicitInterp = true; - if (parent.perPrimitiveNV) - child.perPrimitiveNV = true; - if (parent.perViewNV) - child.perViewNV = true; - if (parent.perTaskNV) - child.perTaskNV = true; - if (parent.storage == glslang::EvqtaskPayloadSharedEXT) - child.storage = glslang::EvqtaskPayloadSharedEXT; - if (parent.patch) - child.patch = true; - if (parent.sample) - child.sample = true; - if (parent.coherent) - child.coherent = true; - if (parent.devicecoherent) - child.devicecoherent = true; - if (parent.queuefamilycoherent) - child.queuefamilycoherent = true; - if (parent.workgroupcoherent) - child.workgroupcoherent = true; - if (parent.subgroupcoherent) - child.subgroupcoherent = true; - if (parent.shadercallcoherent) - child.shadercallcoherent = true; - if (parent.nonprivate) - child.nonprivate = true; - if (parent.volatil) - child.volatil = true; - if (parent.restrict) - child.restrict = true; - if (parent.readonly) - child.readonly = true; - if (parent.writeonly) - child.writeonly = true; - if (parent.nonUniform) - child.nonUniform = true; -} - -bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier) -{ - // This should list qualifiers that simultaneous satisfy: - // - struct members might inherit from a struct declaration - // (note that non-block structs don't explicitly inherit, - // only implicitly, meaning no decoration involved) - // - affect decorations on the struct members - // (note smooth does not, and expecting something like volatile - // to effect the whole object) - // - are not part of the offset/st430/etc or row/column-major layout - return qualifier.invariant || (qualifier.hasLocation() && type.getBasicType() == glslang::EbtBlock); -} - -// -// Implement the TGlslangToSpvTraverser class. -// - -TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, - const glslang::TIntermediate* glslangIntermediate, - spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) : - TIntermTraverser(true, false, true), - options(options), - shaderEntry(nullptr), currentFunction(nullptr), - sequenceDepth(0), logger(buildLogger), - builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), - inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), - glslangIntermediate(glslangIntermediate), - nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()), - nonSemanticDebugPrintf(0), - taskPayloadID(0) -{ - bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) != - glslangIntermediate->getRequestedExtensions().end()); - spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage(), isMeshShaderExt); - - builder.clearAccessChain(); - builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), - glslangIntermediate->getVersion()); - - if (options.emitNonSemanticShaderDebugSource) - this->options.emitNonSemanticShaderDebugInfo = true; - if (options.emitNonSemanticShaderDebugInfo) - this->options.generateDebugInfo = true; - - if (this->options.generateDebugInfo) { - if (this->options.emitNonSemanticShaderDebugInfo) { - builder.setEmitNonSemanticShaderDebugInfo(this->options.emitNonSemanticShaderDebugSource); - } - else { - builder.setEmitSpirvDebugInfo(); - } - builder.setDebugMainSourceFile(glslangIntermediate->getSourceFile()); - - // Set the source shader's text. If for SPV version 1.0, include - // a preamble in comments stating the OpModuleProcessed instructions. - // Otherwise, emit those as actual instructions. - std::string text; - const std::vector& processes = glslangIntermediate->getProcesses(); - for (int p = 0; p < (int)processes.size(); ++p) { - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_1) { - text.append("// OpModuleProcessed "); - text.append(processes[p]); - text.append("\n"); - } else - builder.addModuleProcessed(processes[p]); - } - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_1 && (int)processes.size() > 0) - text.append("#line 1\n"); - text.append(glslangIntermediate->getSourceText()); - builder.setSourceText(text); - // Pass name and text for all included files - const std::map& include_txt = glslangIntermediate->getIncludeText(); - for (auto iItr = include_txt.begin(); iItr != include_txt.end(); ++iItr) - builder.addInclude(iItr->first, iItr->second); - } - - builder.setUseReplicatedComposites(glslangIntermediate->usingReplicatedComposites()); - - stdBuiltins = builder.import("GLSL.std.450"); - - spv::AddressingModel addressingModel = spv::AddressingModelLogical; - spv::MemoryModel memoryModel = spv::MemoryModelGLSL450; - - if (glslangIntermediate->usingPhysicalStorageBuffer()) { - addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT; - builder.addIncorporatedExtension(spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT); - } - if (glslangIntermediate->usingVulkanMemoryModel()) { - memoryModel = spv::MemoryModelVulkanKHR; - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - builder.addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); - } - builder.setMemoryModel(addressingModel, memoryModel); - - if (glslangIntermediate->usingVariablePointers()) { - builder.addCapability(spv::CapabilityVariablePointers); - } - - // If not linking, there is no entry point - if (!options.compileOnly) { - shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str()); - entryPoint = - builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str()); - } - - // Add the source extensions - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it) - builder.addSourceExtension(it->c_str()); - - // Add the top-level modes for this shader. - - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb); - } - - if (glslangIntermediate->getLayoutPrimitiveCulling()) { - builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR); - } - - if (glslangIntermediate->getSubgroupUniformControlFlow()) { - builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR); - } - if (glslangIntermediate->getMaximallyReconverges()) { - builder.addExtension(spv::E_SPV_KHR_maximal_reconvergence); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeMaximallyReconvergesKHR); - } - - if (glslangIntermediate->getQuadDerivMode()) - { - builder.addCapability(spv::CapabilityQuadControlKHR); - builder.addExtension(spv::E_SPV_KHR_quad_control); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeQuadDerivativesKHR); - } - - if (glslangIntermediate->getReqFullQuadsMode()) - { - builder.addCapability(spv::CapabilityQuadControlKHR); - builder.addExtension(spv::E_SPV_KHR_quad_control); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeRequireFullQuadsKHR); - } - - unsigned int mode; - switch (glslangIntermediate->getStage()) { - case EShLangVertex: - builder.addCapability(spv::CapabilityShader); - break; - - case EShLangFragment: - builder.addCapability(spv::CapabilityShader); - if (glslangIntermediate->getPixelCenterInteger()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger); - - if (glslangIntermediate->getOriginUpperLeft()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft); - else - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft); - - if (glslangIntermediate->getEarlyFragmentTests()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); - - if (glslangIntermediate->getEarlyAndLateFragmentTestsAMD()) - { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyAndLateFragmentTestsAMD); - builder.addExtension(spv::E_SPV_AMD_shader_early_and_late_fragment_tests); - } - - if (glslangIntermediate->getPostDepthCoverage()) { - builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); - builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); - builder.addExtension(spv::E_SPV_KHR_post_depth_coverage); - } - - if (glslangIntermediate->getNonCoherentColorAttachmentReadEXT()) { - builder.addCapability(spv::CapabilityTileImageColorReadAccessEXT); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeNonCoherentColorAttachmentReadEXT); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - } - - if (glslangIntermediate->getNonCoherentDepthAttachmentReadEXT()) { - builder.addCapability(spv::CapabilityTileImageDepthReadAccessEXT); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeNonCoherentDepthAttachmentReadEXT); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - } - - if (glslangIntermediate->getNonCoherentStencilAttachmentReadEXT()) { - builder.addCapability(spv::CapabilityTileImageStencilReadAccessEXT); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeNonCoherentStencilAttachmentReadEXT); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - } - - if (glslangIntermediate->isDepthReplacing()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); - - if (glslangIntermediate->isStencilReplacing()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeStencilRefReplacingEXT); - - switch(glslangIntermediate->getDepth()) { - case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; - case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; - case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break; - default: mode = spv::ExecutionModeMax; break; - } - - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getStencil()) { - case glslang::ElsRefUnchangedFrontAMD: mode = spv::ExecutionModeStencilRefUnchangedFrontAMD; break; - case glslang::ElsRefGreaterFrontAMD: mode = spv::ExecutionModeStencilRefGreaterFrontAMD; break; - case glslang::ElsRefLessFrontAMD: mode = spv::ExecutionModeStencilRefLessFrontAMD; break; - case glslang::ElsRefUnchangedBackAMD: mode = spv::ExecutionModeStencilRefUnchangedBackAMD; break; - case glslang::ElsRefGreaterBackAMD: mode = spv::ExecutionModeStencilRefGreaterBackAMD; break; - case glslang::ElsRefLessBackAMD: mode = spv::ExecutionModeStencilRefLessBackAMD; break; - default: mode = spv::ExecutionModeMax; break; - } - - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - switch (glslangIntermediate->getInterlockOrdering()) { - case glslang::EioPixelInterlockOrdered: mode = spv::ExecutionModePixelInterlockOrderedEXT; - break; - case glslang::EioPixelInterlockUnordered: mode = spv::ExecutionModePixelInterlockUnorderedEXT; - break; - case glslang::EioSampleInterlockOrdered: mode = spv::ExecutionModeSampleInterlockOrderedEXT; - break; - case glslang::EioSampleInterlockUnordered: mode = spv::ExecutionModeSampleInterlockUnorderedEXT; - break; - case glslang::EioShadingRateInterlockOrdered: mode = spv::ExecutionModeShadingRateInterlockOrderedEXT; - break; - case glslang::EioShadingRateInterlockUnordered: mode = spv::ExecutionModeShadingRateInterlockUnorderedEXT; - break; - default: mode = spv::ExecutionModeMax; - break; - } - if (mode != spv::ExecutionModeMax) { - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - if (mode == spv::ExecutionModeShadingRateInterlockOrderedEXT || - mode == spv::ExecutionModeShadingRateInterlockUnorderedEXT) { - builder.addCapability(spv::CapabilityFragmentShaderShadingRateInterlockEXT); - } else if (mode == spv::ExecutionModePixelInterlockOrderedEXT || - mode == spv::ExecutionModePixelInterlockUnorderedEXT) { - builder.addCapability(spv::CapabilityFragmentShaderPixelInterlockEXT); - } else { - builder.addCapability(spv::CapabilityFragmentShaderSampleInterlockEXT); - } - builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); - } - break; - - case EShLangCompute: { - builder.addCapability(spv::CapabilityShader); - bool needSizeId = false; - for (int dim = 0; dim < 3; ++dim) { - if ((glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet)) { - needSizeId = true; - break; - } - } - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6 && needSizeId) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); - needSizeId = true; - } - } - builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId); - } else { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); - } - if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) { - builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV); - builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); - } else if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupLinear) { - builder.addCapability(spv::CapabilityComputeDerivativeGroupLinearNV); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupLinearNV); - builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); - } - break; - } - case EShLangTessEvaluation: - case EShLangTessControl: - builder.addCapability(spv::CapabilityTessellation); - - glslang::TLayoutGeometry primitive; - - if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, - glslangIntermediate->getVertices()); - primitive = glslangIntermediate->getOutputPrimitive(); - } else { - primitive = glslangIntermediate->getInputPrimitive(); - } - - switch (primitive) { - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgQuads: mode = spv::ExecutionModeQuads; break; - case glslang::ElgIsolines: mode = spv::ExecutionModeIsolines; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexSpacing()) { - case glslang::EvsEqual: mode = spv::ExecutionModeSpacingEqual; break; - case glslang::EvsFractionalEven: mode = spv::ExecutionModeSpacingFractionalEven; break; - case glslang::EvsFractionalOdd: mode = spv::ExecutionModeSpacingFractionalOdd; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexOrder()) { - case glslang::EvoCw: mode = spv::ExecutionModeVertexOrderCw; break; - case glslang::EvoCcw: mode = spv::ExecutionModeVertexOrderCcw; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - if (glslangIntermediate->getPointMode()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePointMode); - break; - - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometry); - switch (glslangIntermediate->getInputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeInputPoints; break; - case glslang::ElgLines: mode = spv::ExecutionModeInputLines; break; - case glslang::ElgLinesAdjacency: mode = spv::ExecutionModeInputLinesAdjacency; break; - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations()); - - switch (glslangIntermediate->getOutputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; - case glslang::ElgLineStrip: mode = spv::ExecutionModeOutputLineStrip; break; - case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - break; - - case EShLangRayGen: - case EShLangIntersect: - case EShLangAnyHit: - case EShLangClosestHit: - case EShLangMiss: - case EShLangCallable: - { - auto& extensions = glslangIntermediate->getRequestedExtensions(); - if (extensions.find("GL_NV_ray_tracing") == extensions.end()) { - builder.addCapability(spv::CapabilityRayTracingKHR); - builder.addExtension("SPV_KHR_ray_tracing"); - } - else { - builder.addCapability(spv::CapabilityRayTracingNV); - builder.addExtension("SPV_NV_ray_tracing"); - } - if (glslangIntermediate->getStage() != EShLangRayGen && glslangIntermediate->getStage() != EShLangCallable) { - if (extensions.find("GL_EXT_ray_cull_mask") != extensions.end()) { - builder.addCapability(spv::CapabilityRayCullMaskKHR); - builder.addExtension("SPV_KHR_ray_cull_mask"); - } - if (extensions.find("GL_EXT_ray_tracing_position_fetch") != extensions.end()) { - builder.addCapability(spv::CapabilityRayTracingPositionFetchKHR); - builder.addExtension("SPV_KHR_ray_tracing_position_fetch"); - } - } - break; - } - case EShLangTask: - case EShLangMesh: - if(isMeshShaderExt) { - builder.addCapability(spv::CapabilityMeshShadingEXT); - builder.addExtension(spv::E_SPV_EXT_mesh_shader); - } else { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); - } - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); - } - } - builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId); - } else { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); - } - if (glslangIntermediate->getStage() == EShLangMesh) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, - glslangIntermediate->getVertices()); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, - glslangIntermediate->getPrimitives()); - - switch (glslangIntermediate->getOutputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; - case glslang::ElgLines: mode = spv::ExecutionModeOutputLinesNV; break; - case glslang::ElgTriangles: mode = spv::ExecutionModeOutputTrianglesNV; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - } - break; - - default: - break; - } - - // - // Add SPIR-V requirements (GL_EXT_spirv_intrinsics) - // - if (glslangIntermediate->hasSpirvRequirement()) { - const glslang::TSpirvRequirement& spirvRequirement = glslangIntermediate->getSpirvRequirement(); - - // Add SPIR-V extension requirement - for (auto& extension : spirvRequirement.extensions) - builder.addExtension(extension.c_str()); - - // Add SPIR-V capability requirement - for (auto capability : spirvRequirement.capabilities) - builder.addCapability(static_cast(capability)); - } - - // - // Add SPIR-V execution mode qualifiers (GL_EXT_spirv_intrinsics) - // - if (glslangIntermediate->hasSpirvExecutionMode()) { - const glslang::TSpirvExecutionMode spirvExecutionMode = glslangIntermediate->getSpirvExecutionMode(); - - // Add spirv_execution_mode - for (auto& mode : spirvExecutionMode.modes) { - if (!mode.second.empty()) { - std::vector literals; - TranslateLiterals(mode.second, literals); - builder.addExecutionMode(shaderEntry, static_cast(mode.first), literals); - } else - builder.addExecutionMode(shaderEntry, static_cast(mode.first)); - } - - // Add spirv_execution_mode_id - for (auto& modeId : spirvExecutionMode.modeIds) { - std::vector operandIds; - assert(!modeId.second.empty()); - for (auto extraOperand : modeId.second) { - if (extraOperand->getType().getQualifier().isSpecConstant()) - operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode())); - else - operandIds.push_back(createSpvConstant(*extraOperand)); - } - builder.addExecutionModeId(shaderEntry, static_cast(modeId.first), operandIds); - } - } -} - -// Finish creating SPV, after the traversal is complete. -void TGlslangToSpvTraverser::finishSpv(bool compileOnly) -{ - // If not linking, an entry point is not expected - if (!compileOnly) { - // Finish the entry point function - if (!entryPointTerminated) { - builder.setBuildPoint(shaderEntry->getLastBlock()); - builder.leaveFunction(); - } - - // finish off the entry-point SPV instruction by adding the Input/Output - entryPoint->reserveOperands(iOSet.size()); - for (auto id : iOSet) - entryPoint->addIdOperand(id); - } - - // Add capabilities, extensions, remove unneeded decorations, etc., - // based on the resulting SPIR-V. - // Note: WebGPU code generation must have the opportunity to aggressively - // prune unreachable merge blocks and continue targets. - builder.postProcess(compileOnly); -} - -// Write the SPV into 'out'. -void TGlslangToSpvTraverser::dumpSpv(std::vector& out) -{ - builder.dump(out); -} - -// -// Implement the traversal functions. -// -// Return true from interior nodes to have the external traversal -// continue on to children. Return false if children were -// already processed. -// - -// -// Symbols can turn into -// - uniform/input reads -// - output writes -// - complex lvalue base setups: foo.bar[3].... , where we see foo and start up an access chain -// - something simple that degenerates into the last bullet -// -void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) -{ - // We update the line information even though no code might be generated here - // This is helpful to yield correct lines for control flow instructions - if (!linkageOnly) { - builder.setDebugSourceLocation(symbol->getLoc().line, symbol->getLoc().getFilename()); - } - - if (symbol->getBasicType() == glslang::EbtFunction) { - return; - } - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (symbol->getType().isStruct()) - glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId(); - - if (symbol->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); -#ifdef ENABLE_HLSL - // Skip symbol handling if it is string-typed - if (symbol->getBasicType() == glslang::EbtString) - return; -#endif - - // getSymbolId() will set up all the IO decorations on the first call. - // Formal function parameters were mapped during makeFunctions(). - spv::Id id = getSymbolId(symbol); - - if (symbol->getType().getQualifier().isTaskPayload()) - taskPayloadID = id; // cache the taskPayloadID to be used it as operand for OpEmitMeshTasksEXT - - if (builder.isPointer(id)) { - if (!symbol->getType().getQualifier().isParamInput() && - !symbol->getType().getQualifier().isParamOutput()) { - // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction - // Consider adding to the OpEntryPoint interface list. - // Only looking at structures if they have at least one member. - if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) { - spv::StorageClass sc = builder.getStorageClass(id); - // Before SPIR-V 1.4, we only want to include Input and Output. - // Starting with SPIR-V 1.4, we want all globals. - if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && builder.isGlobalVariable(id)) || - (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)) { - iOSet.insert(id); - } - } - } - - // If the SPIR-V type is required to be different than the AST type - // (for ex SubgroupMasks or 3x4 ObjectToWorld/WorldToObject matrices), - // translate now from the SPIR-V type to the AST type, for the consuming - // operation. - // Note this turns it from an l-value to an r-value. - // Currently, all symbols needing this are inputs; avoid the map lookup when non-input. - if (symbol->getType().getQualifier().storage == glslang::EvqVaryingIn) - id = translateForcedType(id); - } - - // Only process non-linkage-only nodes for generating actual static uses - if (! linkageOnly || symbol->getQualifier().isSpecConstant()) { - // Prepare to generate code for the access - - // L-value chains will be computed left to right. We're on the symbol now, - // which is the left-most part of the access chain, so now is "clear" time, - // followed by setting the base. - builder.clearAccessChain(); - - // For now, we consider all user variables as being in memory, so they are pointers, - // except for - // A) R-Value arguments to a function, which are an intermediate object. - // See comments in handleUserFunctionCall(). - // B) Specialization constants (normal constants don't even come in as a variable), - // These are also pure R-values. - // C) R-Values from type translation, see above call to translateForcedType() - glslang::TQualifier qualifier = symbol->getQualifier(); - if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end() || - !builder.isPointerType(builder.getTypeId(id))) - builder.setAccessChainRValue(id); - else - builder.setAccessChainLValue(id); - } - -#ifdef ENABLE_HLSL - // Process linkage-only nodes for any special additional interface work. - if (linkageOnly) { - if (glslangIntermediate->getHlslFunctionality1()) { - // Map implicit counter buffers to their originating buffers, which should have been - // seen by now, given earlier pruning of unused counters, and preservation of order - // of declaration. - if (symbol->getType().getQualifier().isUniformOrBuffer()) { - if (!glslangIntermediate->hasCounterBufferName(symbol->getName())) { - // Save possible originating buffers for counter buffers, keyed by - // making the potential counter-buffer name. - std::string keyName = symbol->getName().c_str(); - keyName = glslangIntermediate->addCounterBufferName(keyName); - counterOriginator[keyName] = symbol; - } else { - // Handle a counter buffer, by finding the saved originating buffer. - std::string keyName = symbol->getName().c_str(); - auto it = counterOriginator.find(keyName); - if (it != counterOriginator.end()) { - id = getSymbolId(it->second); - if (id != spv::NoResult) { - spv::Id counterId = getSymbolId(symbol); - if (counterId != spv::NoResult) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addDecorationId(id, spv::DecorationHlslCounterBufferGOOGLE, counterId); - } - } - } - } - } - } - } -#endif -} - -bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) -{ - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) { - glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId(); - } - if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) { - glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId(); - } - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - // First, handle special cases - switch (node->getOp()) { - case glslang::EOpAssign: - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - case glslang::EOpAndAssign: - case glslang::EOpInclusiveOrAssign: - case glslang::EOpExclusiveOrAssign: - case glslang::EOpLeftShiftAssign: - case glslang::EOpRightShiftAssign: - // A bin-op assign "a += b" means the same thing as "a = a + b" - // where a is evaluated before b. For a simple assignment, GLSL - // says to evaluate the left before the right. So, always, left - // node then right node. - { - // get the left l-value, save it away - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Builder::AccessChain lValue = builder.getAccessChain(); - - // evaluate the right - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id rValue = accessChainLoad(node->getRight()->getType()); - - // reset line number for assignment - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - - if (node->getOp() != glslang::EOpAssign) { - // the left is also an r-value - builder.setAccessChain(lValue); - spv::Id leftRValue = accessChainLoad(node->getLeft()->getType()); - - // do the operation - spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType()); - coherentFlags |= TranslateCoherent(node->getRight()->getType()); - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(coherentFlags) }; - rValue = createBinaryOperation(node->getOp(), decorations, - convertGlslangToSpvType(node->getType()), leftRValue, rValue, - node->getType().getBasicType()); - - // these all need their counterparts in createBinaryOperation() - assert(rValue != spv::NoResult); - } - - // store the result - builder.setAccessChain(lValue); - multiTypeStore(node->getLeft()->getType(), rValue); - - // assignments are expressions having an rValue after they are evaluated... - builder.clearAccessChain(); - builder.setAccessChainRValue(rValue); - } - return false; - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - { - // Structure, array, matrix, or vector indirection with statically known index. - // Get the left part of the access chain. - node->getLeft()->traverse(this); - - // Add the next element in the chain - - const int glslangIndex = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (! node->getLeft()->getType().isArray() && - node->getLeft()->getType().isVector() && - node->getOp() == glslang::EOpIndexDirect) { - // Swizzle is uniform so propagate uniform into access chain - spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType()); - coherentFlags.nonUniform = 0; - // This is essentially a hard-coded vector swizzle of size 1, - // so short circuit the access-chain stuff with a swizzle. - std::vector swizzle; - swizzle.push_back(glslangIndex); - int dummySize; - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), - coherentFlags, - glslangIntermediate->getBaseAlignmentScalar( - node->getLeft()->getType(), dummySize)); - } else { - - // Load through a block reference is performed with a dot operator that - // is mapped to EOpIndexDirectStruct. When we get to the actual reference, - // do a load and reset the access chain. - if (node->getLeft()->isReference() && - !node->getLeft()->getType().isArray() && - node->getOp() == glslang::EOpIndexDirectStruct) - { - spv::Id left = accessChainLoad(node->getLeft()->getType()); - builder.clearAccessChain(); - builder.setAccessChainLValue(left); - } - - int spvIndex = glslangIndex; - if (node->getLeft()->getBasicType() == glslang::EbtBlock && - node->getOp() == glslang::EOpIndexDirectStruct) - { - // This may be, e.g., an anonymous block-member selection, which generally need - // index remapping due to hidden members in anonymous blocks. - long long glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()]; - if (memberRemapper.find(glslangId) != memberRemapper.end()) { - std::vector& remapper = memberRemapper[glslangId]; - assert(remapper.size() > 0); - spvIndex = remapper[glslangIndex]; - } - } - - // Struct reference propagates uniform lvalue - spv::Builder::AccessChain::CoherentFlags coherentFlags = - TranslateCoherent(node->getLeft()->getType()); - coherentFlags.nonUniform = 0; - - // normal case for indexing array or structure or block - builder.accessChainPush(builder.makeIntConstant(spvIndex), - coherentFlags, - node->getLeft()->getType().getBufferReferenceAlignment()); - - // Add capabilities here for accessing PointSize and clip/cull distance. - // We have deferred generation of associated capabilities until now. - if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray()) - declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex); - } - } - return false; - case glslang::EOpIndexIndirect: - { - // Array, matrix, or vector indirection with variable index. - // Will use native SPIR-V access-chain for and array indirection; - // matrices are arrays of vectors, so will also work for a matrix. - // Will use the access chain's 'component' for variable index into a vector. - - // This adapter is building access chains left to right. - // Set up the access chain to the left. - node->getLeft()->traverse(this); - - // save it so that computing the right side doesn't trash it - spv::Builder::AccessChain partial = builder.getAccessChain(); - - // compute the next index in the chain - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id index = accessChainLoad(node->getRight()->getType()); - - addIndirectionIndexCapabilities(node->getLeft()->getType(), node->getRight()->getType()); - - // restore the saved access chain - builder.setAccessChain(partial); - - // Only if index is nonUniform should we propagate nonUniform into access chain - spv::Builder::AccessChain::CoherentFlags index_flags = TranslateCoherent(node->getRight()->getType()); - spv::Builder::AccessChain::CoherentFlags coherent_flags = TranslateCoherent(node->getLeft()->getType()); - coherent_flags.nonUniform = index_flags.nonUniform; - - if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) { - int dummySize; - builder.accessChainPushComponent( - index, convertGlslangToSpvType(node->getLeft()->getType()), coherent_flags, - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), - dummySize)); - } else - builder.accessChainPush(index, coherent_flags, - node->getLeft()->getType().getBufferReferenceAlignment()); - } - return false; - case glslang::EOpVectorSwizzle: - { - node->getLeft()->traverse(this); - std::vector swizzle; - convertSwizzle(*node->getRight()->getAsAggregate(), swizzle); - int dummySize; - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), - TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), - dummySize)); - } - return false; - case glslang::EOpMatrixSwizzle: - logger->missingFunctionality("matrix swizzle"); - return true; - case glslang::EOpLogicalOr: - case glslang::EOpLogicalAnd: - { - - // These may require short circuiting, but can sometimes be done as straight - // binary operations. The right operand must be short circuited if it has - // side effects, and should probably be if it is complex. - if (isTrivial(node->getRight()->getAsTyped())) - break; // handle below as a normal binary operation - // otherwise, we need to do dynamic short circuiting on the right operand - spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), - *node->getRight()->getAsTyped()); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } - return false; - default: - break; - } - - // Assume generic binary op... - - // get right operand - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Id left = accessChainLoad(node->getLeft()->getType()); - - // get left operand - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id right = accessChainLoad(node->getRight()->getType()); - - // get result - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - spv::Id result = createBinaryOperation(node->getOp(), decorations, - convertGlslangToSpvType(node->getType()), left, right, - node->getLeft()->getType().getBasicType()); - - builder.clearAccessChain(); - if (! result) { - logger->missingFunctionality("unknown glslang binary operation"); - return true; // pick up a child as the place-holder result - } else { - builder.setAccessChainRValue(result); - return false; - } -} - -spv::Id TGlslangToSpvTraverser::convertLoadedBoolInUniformToUint(const glslang::TType& type, - spv::Id nominalTypeId, - spv::Id loadedId) -{ - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) - return builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) - loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, - makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } else if (builder.isArrayType(nominalTypeId)) { - // Conversion for bool array - spv::Id boolArrayTypeId = convertGlslangToSpvType(type); - if (nominalTypeId != boolArrayTypeId) - { - // Use OpCopyLogical from SPIR-V 1.4 if available. - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) - return builder.createUnaryOp(spv::OpCopyLogical, boolArrayTypeId, loadedId); - - glslang::TType glslangElementType(type, 0); - spv::Id elementNominalTypeId = builder.getContainedTypeId(nominalTypeId); - std::vector constituents; - for (int index = 0; index < type.getOuterArraySize(); ++index) { - // get the element - spv::Id elementValue = builder.createCompositeExtract(loadedId, elementNominalTypeId, index); - - // recursively convert it - spv::Id elementConvertedValue = convertLoadedBoolInUniformToUint(glslangElementType, elementNominalTypeId, elementValue); - constituents.push_back(elementConvertedValue); - } - return builder.createCompositeConstruct(boolArrayTypeId, constituents); - } - } - - return loadedId; -} - -// Figure out what, if any, type changes are needed when accessing a specific built-in. -// Returns . -// Also see comment for 'forceType', regarding tracking SPIR-V-required types. -std::pair TGlslangToSpvTraverser::getForcedType(glslang::TBuiltInVariable glslangBuiltIn, - const glslang::TType& glslangType) -{ - switch(glslangBuiltIn) - { - case glslang::EbvSubGroupEqMask: - case glslang::EbvSubGroupGeMask: - case glslang::EbvSubGroupGtMask: - case glslang::EbvSubGroupLeMask: - case glslang::EbvSubGroupLtMask: { - // these require changing a 64-bit scaler -> a vector of 32-bit components - if (glslangType.isVector()) - break; - spv::Id ivec4_type = builder.makeVectorType(builder.makeUintType(32), 4); - spv::Id uint64_type = builder.makeUintType(64); - std::pair ret(ivec4_type, uint64_type); - return ret; - } - // There are no SPIR-V builtins defined for these and map onto original non-transposed - // builtins. During visitBinary we insert a transpose - case glslang::EbvWorldToObject3x4: - case glslang::EbvObjectToWorld3x4: { - spv::Id mat43 = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - spv::Id mat34 = builder.makeMatrixType(builder.makeFloatType(32), 3, 4); - std::pair ret(mat43, mat34); - return ret; - } - default: - break; - } - - std::pair ret(spv::NoType, spv::NoType); - return ret; -} - -// For an object previously identified (see getForcedType() and forceType) -// as needing type translations, do the translation needed for a load, turning -// an L-value into in R-value. -spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object) -{ - const auto forceIt = forceType.find(object); - if (forceIt == forceType.end()) - return object; - - spv::Id desiredTypeId = forceIt->second; - spv::Id objectTypeId = builder.getTypeId(object); - assert(builder.isPointerType(objectTypeId)); - objectTypeId = builder.getContainedTypeId(objectTypeId); - if (builder.isVectorType(objectTypeId) && - builder.getScalarTypeWidth(builder.getContainedTypeId(objectTypeId)) == 32) { - if (builder.getScalarTypeWidth(desiredTypeId) == 64) { - // handle 32-bit v.xy* -> 64-bit - builder.clearAccessChain(); - builder.setAccessChainLValue(object); - object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId); - std::vector components; - components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0)); - components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1)); - - spv::Id vecType = builder.makeVectorType(builder.getContainedTypeId(objectTypeId), 2); - return builder.createUnaryOp(spv::OpBitcast, desiredTypeId, - builder.createCompositeConstruct(vecType, components)); - } else { - logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar"); - } - } else if (builder.isMatrixType(objectTypeId)) { - // There are no SPIR-V builtins defined for 3x4 variants of ObjectToWorld/WorldToObject - // and we insert a transpose after loading the original non-transposed builtins - builder.clearAccessChain(); - builder.setAccessChainLValue(object); - object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId); - return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object); - - } else { - logger->missingFunctionality("forcing non 32-bit vector type"); - } - - return object; -} - -bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) -{ - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - - // try texturing first - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // Non-texturing. - - if (node->getOp() == glslang::EOpArrayLength) { - // Quite special; won't want to evaluate the operand. - - // Currently, the front-end does not allow .length() on an array until it is sized, - // except for the last block membeor of an SSBO. - // TODO: If this changes, link-time sized arrays might show up here, and need their - // size extracted. - - // Normal .length() would have been constant folded by the front-end. - // So, this has to be block.lastMember.length(). - // SPV wants "block" and member number as the operands, go get them. - - spv::Id length; - if (node->getOperand()->getType().isCoopMat()) { - spv::Id typeId = convertGlslangToSpvType(node->getOperand()->getType()); - assert(builder.isCooperativeMatrixType(typeId)); - - if (node->getOperand()->getType().isCoopMatKHR()) { - length = builder.createCooperativeMatrixLengthKHR(typeId); - } else { - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - length = builder.createCooperativeMatrixLengthNV(typeId); - } - } else { - glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft(); - block->traverse(this); - unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion() - ->getConstArray()[0].getUConst(); - length = builder.createArrayLength(builder.accessChainGetLValue(), member); - } - - // GLSL semantics say the result of .length() is an int, while SPIR-V says - // signedness must be 0. So, convert from SPIR-V unsigned back to GLSL's - // AST expectation of a signed result. - if (glslangIntermediate->getSource() == glslang::EShSourceGlsl) { - if (builder.isInSpecConstCodeGenMode()) { - length = builder.createBinOp(spv::OpIAdd, builder.makeIntType(32), length, builder.makeIntConstant(0)); - } else { - length = builder.createUnaryOp(spv::OpBitcast, builder.makeIntType(32), length); - } - } - - builder.clearAccessChain(); - builder.setAccessChainRValue(length); - - return false; - } - - // Force variable declaration - Debug Mode Only - if (node->getOp() == glslang::EOpDeclare) { - builder.clearAccessChain(); - node->getOperand()->traverse(this); - builder.clearAccessChain(); - return false; - } - - // Start by evaluating the operand - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - spv::Id invertedType = spv::NoType; - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? - invertedType : convertGlslangToSpvType(node->getType()); }; - if (node->getOp() == glslang::EOpInterpolateAtCentroid) - invertedType = getInvertedSwizzleType(*node->getOperand()); - - builder.clearAccessChain(); - TIntermNode *operandNode; - if (invertedType != spv::NoType) - operandNode = node->getOperand()->getAsBinaryNode()->getLeft(); - else - operandNode = node->getOperand(); - - operandNode->traverse(this); - - spv::Id operand = spv::NoResult; - - spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; - - const auto hitObjectOpsWithLvalue = [](glslang::TOperator op) { - switch(op) { - case glslang::EOpReorderThreadNV: - case glslang::EOpHitObjectGetCurrentTimeNV: - case glslang::EOpHitObjectGetHitKindNV: - case glslang::EOpHitObjectGetPrimitiveIndexNV: - case glslang::EOpHitObjectGetGeometryIndexNV: - case glslang::EOpHitObjectGetInstanceIdNV: - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - case glslang::EOpHitObjectGetObjectRayDirectionNV: - case glslang::EOpHitObjectGetObjectRayOriginNV: - case glslang::EOpHitObjectGetWorldRayDirectionNV: - case glslang::EOpHitObjectGetWorldRayOriginNV: - case glslang::EOpHitObjectGetWorldToObjectNV: - case glslang::EOpHitObjectGetObjectToWorldNV: - case glslang::EOpHitObjectGetRayTMaxNV: - case glslang::EOpHitObjectGetRayTMinNV: - case glslang::EOpHitObjectIsEmptyNV: - case glslang::EOpHitObjectIsHitNV: - case glslang::EOpHitObjectIsMissNV: - case glslang::EOpHitObjectRecordEmptyNV: - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - return true; - default: - return false; - } - }; - - if (node->getOp() == glslang::EOpAtomicCounterIncrement || - node->getOp() == glslang::EOpAtomicCounterDecrement || - node->getOp() == glslang::EOpAtomicCounter || - (node->getOp() == glslang::EOpInterpolateAtCentroid && - glslangIntermediate->getSource() != glslang::EShSourceHlsl) || - node->getOp() == glslang::EOpRayQueryProceed || - node->getOp() == glslang::EOpRayQueryGetRayTMin || - node->getOp() == glslang::EOpRayQueryGetRayFlags || - node->getOp() == glslang::EOpRayQueryGetWorldRayOrigin || - node->getOp() == glslang::EOpRayQueryGetWorldRayDirection || - node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque || - node->getOp() == glslang::EOpRayQueryTerminate || - node->getOp() == glslang::EOpRayQueryConfirmIntersection || - (node->getOp() == glslang::EOpSpirvInst && operandNode->getAsTyped()->getQualifier().isSpirvByReference()) || - hitObjectOpsWithLvalue(node->getOp())) { - operand = builder.accessChainGetLValue(); // Special case l-value operands - lvalueCoherentFlags = builder.getAccessChain().coherentFlags; - lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType()); - } else if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Will be translated to a literal value, make a placeholder here - operand = spv::NoResult; - } else { - operand = accessChainLoad(node->getOperand()->getType()); - } - - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - - // it could be a conversion - if (! result) { - result = createConversion(node->getOp(), decorations, resultType(), operand, - node->getType().getBasicType(), node->getOperand()->getBasicType()); - if (result) { - if (node->getType().isCoopMatKHR() && node->getOperand()->getAsTyped()->getType().isCoopMatKHR() && - !node->getAsTyped()->getType().sameCoopMatUse(node->getOperand()->getAsTyped()->getType())) { - // Conversions that change use need CapabilityCooperativeMatrixConversionsNV - builder.addCapability(spv::CapabilityCooperativeMatrixConversionsNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); - } - } - } - - // if not, then possibly an operation - if (! result) - result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, - node->getOperand()->getBasicType(), lvalueCoherentFlags, node->getType()); - - // it could be attached to a SPIR-V intruction - if (!result) { - if (node->getOp() == glslang::EOpSpirvInst) { - const auto& spirvInst = node->getSpirvInstruction(); - if (spirvInst.set == "") { - spv::IdImmediate idImmOp = {true, operand}; - if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Translate the constant to a literal value - std::vector literals; - glslang::TVector constants; - constants.push_back(operandNode->getAsConstantUnion()); - TranslateLiterals(constants, literals); - idImmOp = {false, literals[0]}; - } - - if (node->getBasicType() == glslang::EbtVoid) - builder.createNoResultOp(static_cast(spirvInst.id), {idImmOp}); - else - result = builder.createOp(static_cast(spirvInst.id), resultType(), {idImmOp}); - } else { - result = builder.createBuiltinCall( - resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()), - spirvInst.id, {operand}); - } - - if (node->getBasicType() == glslang::EbtVoid) - return false; // done with this node - } - } - - if (result) { - if (invertedType) { - result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result); - decorations.addNonUniform(builder, result); - } - - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // it must be a special case, check... - switch (node->getOp()) { - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - { - // we need the integer value "1" or the floating point "1.0" to add/subtract - spv::Id one = 0; - if (node->getBasicType() == glslang::EbtFloat) - one = builder.makeFloatConstant(1.0F); - else if (node->getBasicType() == glslang::EbtDouble) - one = builder.makeDoubleConstant(1.0); - else if (node->getBasicType() == glslang::EbtFloat16) - one = builder.makeFloat16Constant(1.0F); - else if (node->getBasicType() == glslang::EbtInt8 || node->getBasicType() == glslang::EbtUint8) - one = builder.makeInt8Constant(1); - else if (node->getBasicType() == glslang::EbtInt16 || node->getBasicType() == glslang::EbtUint16) - one = builder.makeInt16Constant(1); - else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64) - one = builder.makeInt64Constant(1); - else - one = builder.makeIntConstant(1); - glslang::TOperator op; - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPostIncrement) - op = glslang::EOpAdd; - else - op = glslang::EOpSub; - - spv::Id result = createBinaryOperation(op, decorations, - convertGlslangToSpvType(node->getType()), operand, one, - node->getType().getBasicType()); - assert(result != spv::NoResult); - - // The result of operation is always stored, but conditionally the - // consumed result. The consumed result is always an r-value. - builder.accessChainStore(result, - TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags)); - builder.clearAccessChain(); - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPreDecrement) - builder.setAccessChainRValue(result); - else - builder.setAccessChainRValue(operand); - } - - return false; - - case glslang::EOpAssumeEXT: - builder.addCapability(spv::CapabilityExpectAssumeKHR); - builder.addExtension(spv::E_SPV_KHR_expect_assume); - builder.createNoResultOp(spv::OpAssumeTrueKHR, operand); - return false; - case glslang::EOpEmitStreamVertex: - builder.createNoResultOp(spv::OpEmitStreamVertex, operand); - return false; - case glslang::EOpEndStreamPrimitive: - builder.createNoResultOp(spv::OpEndStreamPrimitive, operand); - return false; - case glslang::EOpRayQueryTerminate: - builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operand); - return false; - case glslang::EOpRayQueryConfirmIntersection: - builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operand); - return false; - case glslang::EOpReorderThreadNV: - builder.createNoResultOp(spv::OpReorderThreadWithHitObjectNV, operand); - return false; - case glslang::EOpHitObjectRecordEmptyNV: - builder.createNoResultOp(spv::OpHitObjectRecordEmptyNV, operand); - return false; - - case glslang::EOpCreateTensorLayoutNV: - result = builder.createOp(spv::OpCreateTensorLayoutNV, resultType(), std::vector{}); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - return false; - - case glslang::EOpCreateTensorViewNV: - result = builder.createOp(spv::OpCreateTensorViewNV, resultType(), std::vector{}); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - return false; - - default: - logger->missingFunctionality("unknown glslang unary"); - return true; // pick up operand as placeholder result - } -} - -// Construct a composite object, recursively copying members if their types don't match -spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, std::vector constituents) -{ - for (int c = 0; c < (int)constituents.size(); ++c) { - spv::Id& constituent = constituents[c]; - spv::Id lType = builder.getContainedTypeId(resultTypeId, c); - spv::Id rType = builder.getTypeId(constituent); - if (lType != rType) { - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { - constituent = builder.createUnaryOp(spv::OpCopyLogical, lType, constituent); - } else if (builder.isStructType(rType)) { - std::vector rTypeConstituents; - int numrTypeConstituents = builder.getNumTypeConstituents(rType); - for (int i = 0; i < numrTypeConstituents; ++i) { - rTypeConstituents.push_back(builder.createCompositeExtract(constituent, - builder.getContainedTypeId(rType, i), i)); - } - constituents[c] = createCompositeConstruct(lType, rTypeConstituents); - } else { - assert(builder.isArrayType(rType)); - std::vector rTypeConstituents; - int numrTypeConstituents = builder.getNumTypeConstituents(rType); - - spv::Id elementRType = builder.getContainedTypeId(rType); - for (int i = 0; i < numrTypeConstituents; ++i) { - rTypeConstituents.push_back(builder.createCompositeExtract(constituent, elementRType, i)); - } - constituents[c] = createCompositeConstruct(lType, rTypeConstituents); - } - } - } - return builder.createCompositeConstruct(resultTypeId, constituents); -} - -bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node) -{ - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - spv::Id invertedType = spv::NoType; // to use to override the natural type of the node - std::vector complexLvalues; // for holding swizzling l-values too complex for - // SPIR-V, for an out parameter - std::vector temporaryLvalues; // temporaries to pass, as proxies for complexLValues - - auto resultType = [&invertedType, &node, this](){ - if (invertedType != spv::NoType) { - return invertedType; - } else { - auto ret = convertGlslangToSpvType(node->getType()); - // convertGlslangToSpvType may clobber the debug location, reset it - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - return ret; - } - }; - - // try texturing - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; - } else if (node->getOp() == glslang::EOpImageStore || - node->getOp() == glslang::EOpImageStoreLod || - node->getOp() == glslang::EOpImageAtomicStore) { - // "imageStore" is a special case, which has no result - return false; - } - - glslang::TOperator binOp = glslang::EOpNull; - bool reduceComparison = true; - bool isMatrix = false; - bool noReturnValue = false; - bool atomic = false; - - spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; - - assert(node->getOp()); - - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); - - switch (node->getOp()) { - case glslang::EOpScope: - case glslang::EOpSequence: - { - if (visit == glslang::EvPreVisit) { - ++sequenceDepth; - if (sequenceDepth == 1) { - // If this is the parent node of all the functions, we want to see them - // early, so all call points have actual SPIR-V functions to reference. - // In all cases, still let the traverser visit the children for us. - makeFunctions(node->getAsAggregate()->getSequence()); - - // Global initializers is specific to the shader entry point, which does not exist in compile-only mode - if (!options.compileOnly) { - // Also, we want all globals initializers to go into the beginning of the entry point, before - // anything else gets there, so visit out of order, doing them all now. - makeGlobalInitializers(node->getAsAggregate()->getSequence()); - } - - //Pre process linker objects for ray tracing stages - if (glslangIntermediate->isRayTracingStage()) - collectRayTracingLinkerObjects(); - - // Initializers are done, don't want to visit again, but functions and link objects need to be processed, - // so do them manually. - visitFunctions(node->getAsAggregate()->getSequence()); - - return false; - } else { - if (node->getOp() == glslang::EOpScope) { - auto loc = node->getLoc(); - builder.enterLexicalBlock(loc.line, loc.column); - } - } - } else { - if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope) - builder.leaveLexicalBlock(); - --sequenceDepth; - } - - return true; - } - case glslang::EOpLinkerObjects: - { - if (visit == glslang::EvPreVisit) - linkageOnly = true; - else - linkageOnly = false; - - return true; - } - case glslang::EOpComma: - { - // processing from left to right naturally leaves the right-most - // lying around in the access chain - glslang::TIntermSequence& glslangOperands = node->getSequence(); - for (int i = 0; i < (int)glslangOperands.size(); ++i) - glslangOperands[i]->traverse(this); - - return false; - } - case glslang::EOpFunction: - if (visit == glslang::EvPreVisit) { - if (options.generateDebugInfo) { - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - } - if (isShaderEntryPoint(node)) { - inEntryPoint = true; - builder.setBuildPoint(shaderEntry->getLastBlock()); - builder.enterFunction(shaderEntry); - currentFunction = shaderEntry; - } else { - handleFunctionEntry(node); - } - if (options.generateDebugInfo && !options.emitNonSemanticShaderDebugInfo) { - const auto& loc = node->getLoc(); - const char* sourceFileName = loc.getFilename(); - spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getMainFileId(); - currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column); - } - } else { - if (options.generateDebugInfo) { - if (glslangIntermediate->getSource() == glslang::EShSourceGlsl && node->getSequence().size() > 1) { - auto endLoc = node->getSequence()[1]->getAsAggregate()->getEndLoc(); - builder.setDebugSourceLocation(endLoc.line, endLoc.getFilename()); - } - } - if (inEntryPoint) - entryPointTerminated = true; - builder.leaveFunction(); - inEntryPoint = false; - } - - return true; - case glslang::EOpParameters: - // Parameters will have been consumed by EOpFunction processing, but not - // the body, so we still visited the function node's children, making this - // child redundant. - return false; - case glslang::EOpFunctionCall: - { - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - if (node->isUserDefined()) - result = handleUserFunctionCall(node); - if (result) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } else - logger->missingFunctionality("missing user function; linker needs to catch that"); - - return false; - } - case glslang::EOpConstructMat2x2: - case glslang::EOpConstructMat2x3: - case glslang::EOpConstructMat2x4: - case glslang::EOpConstructMat3x2: - case glslang::EOpConstructMat3x3: - case glslang::EOpConstructMat3x4: - case glslang::EOpConstructMat4x2: - case glslang::EOpConstructMat4x3: - case glslang::EOpConstructMat4x4: - case glslang::EOpConstructDMat2x2: - case glslang::EOpConstructDMat2x3: - case glslang::EOpConstructDMat2x4: - case glslang::EOpConstructDMat3x2: - case glslang::EOpConstructDMat3x3: - case glslang::EOpConstructDMat3x4: - case glslang::EOpConstructDMat4x2: - case glslang::EOpConstructDMat4x3: - case glslang::EOpConstructDMat4x4: - case glslang::EOpConstructIMat2x2: - case glslang::EOpConstructIMat2x3: - case glslang::EOpConstructIMat2x4: - case glslang::EOpConstructIMat3x2: - case glslang::EOpConstructIMat3x3: - case glslang::EOpConstructIMat3x4: - case glslang::EOpConstructIMat4x2: - case glslang::EOpConstructIMat4x3: - case glslang::EOpConstructIMat4x4: - case glslang::EOpConstructUMat2x2: - case glslang::EOpConstructUMat2x3: - case glslang::EOpConstructUMat2x4: - case glslang::EOpConstructUMat3x2: - case glslang::EOpConstructUMat3x3: - case glslang::EOpConstructUMat3x4: - case glslang::EOpConstructUMat4x2: - case glslang::EOpConstructUMat4x3: - case glslang::EOpConstructUMat4x4: - case glslang::EOpConstructBMat2x2: - case glslang::EOpConstructBMat2x3: - case glslang::EOpConstructBMat2x4: - case glslang::EOpConstructBMat3x2: - case glslang::EOpConstructBMat3x3: - case glslang::EOpConstructBMat3x4: - case glslang::EOpConstructBMat4x2: - case glslang::EOpConstructBMat4x3: - case glslang::EOpConstructBMat4x4: - case glslang::EOpConstructF16Mat2x2: - case glslang::EOpConstructF16Mat2x3: - case glslang::EOpConstructF16Mat2x4: - case glslang::EOpConstructF16Mat3x2: - case glslang::EOpConstructF16Mat3x3: - case glslang::EOpConstructF16Mat3x4: - case glslang::EOpConstructF16Mat4x2: - case glslang::EOpConstructF16Mat4x3: - case glslang::EOpConstructF16Mat4x4: - isMatrix = true; - [[fallthrough]]; - case glslang::EOpConstructFloat: - case glslang::EOpConstructVec2: - case glslang::EOpConstructVec3: - case glslang::EOpConstructVec4: - case glslang::EOpConstructDouble: - case glslang::EOpConstructDVec2: - case glslang::EOpConstructDVec3: - case glslang::EOpConstructDVec4: - case glslang::EOpConstructFloat16: - case glslang::EOpConstructF16Vec2: - case glslang::EOpConstructF16Vec3: - case glslang::EOpConstructF16Vec4: - case glslang::EOpConstructBool: - case glslang::EOpConstructBVec2: - case glslang::EOpConstructBVec3: - case glslang::EOpConstructBVec4: - case glslang::EOpConstructInt8: - case glslang::EOpConstructI8Vec2: - case glslang::EOpConstructI8Vec3: - case glslang::EOpConstructI8Vec4: - case glslang::EOpConstructUint8: - case glslang::EOpConstructU8Vec2: - case glslang::EOpConstructU8Vec3: - case glslang::EOpConstructU8Vec4: - case glslang::EOpConstructInt16: - case glslang::EOpConstructI16Vec2: - case glslang::EOpConstructI16Vec3: - case glslang::EOpConstructI16Vec4: - case glslang::EOpConstructUint16: - case glslang::EOpConstructU16Vec2: - case glslang::EOpConstructU16Vec3: - case glslang::EOpConstructU16Vec4: - case glslang::EOpConstructInt: - case glslang::EOpConstructIVec2: - case glslang::EOpConstructIVec3: - case glslang::EOpConstructIVec4: - case glslang::EOpConstructUint: - case glslang::EOpConstructUVec2: - case glslang::EOpConstructUVec3: - case glslang::EOpConstructUVec4: - case glslang::EOpConstructInt64: - case glslang::EOpConstructI64Vec2: - case glslang::EOpConstructI64Vec3: - case glslang::EOpConstructI64Vec4: - case glslang::EOpConstructUint64: - case glslang::EOpConstructU64Vec2: - case glslang::EOpConstructU64Vec3: - case glslang::EOpConstructU64Vec4: - case glslang::EOpConstructStruct: - case glslang::EOpConstructTextureSampler: - case glslang::EOpConstructReference: - case glslang::EOpConstructCooperativeMatrixNV: - case glslang::EOpConstructCooperativeMatrixKHR: - { - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - std::vector arguments; - translateArguments(*node, arguments, lvalueCoherentFlags); - spv::Id constructed; - if (node->getOp() == glslang::EOpConstructTextureSampler) { - const glslang::TType& texType = node->getSequence()[0]->getAsTyped()->getType(); - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6 && - texType.getSampler().isBuffer()) { - // SamplerBuffer is not supported in spirv1.6 so - // `samplerBuffer(textureBuffer, sampler)` is a no-op - // and textureBuffer is the result going forward - constructed = arguments[0]; - } else - constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments); - } else if (node->getOp() == glslang::EOpConstructCooperativeMatrixKHR && - node->getType().isCoopMatKHR() && node->getSequence()[0]->getAsTyped()->getType().isCoopMatKHR()) { - builder.addCapability(spv::CapabilityCooperativeMatrixConversionsNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); - constructed = builder.createCooperativeMatrixConversion(resultType(), arguments[0]); - } else if (node->getOp() == glslang::EOpConstructStruct || - node->getOp() == glslang::EOpConstructCooperativeMatrixNV || - node->getOp() == glslang::EOpConstructCooperativeMatrixKHR || - node->getType().isArray()) { - std::vector constituents; - for (int c = 0; c < (int)arguments.size(); ++c) - constituents.push_back(arguments[c]); - constructed = createCompositeConstruct(resultType(), constituents); - } else if (isMatrix) - constructed = builder.createMatrixConstructor(precision, arguments, resultType()); - else - constructed = builder.createConstructor(precision, arguments, resultType()); - - if (node->getType().getQualifier().isNonUniform()) { - builder.addDecoration(constructed, spv::DecorationNonUniformEXT); - } - - builder.clearAccessChain(); - builder.setAccessChainRValue(constructed); - - return false; - } - - // These six are component-wise compares with component-wise results. - // Forward on to createBinaryOperation(), requesting a vector result. - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - { - // Map the operation to a binary - binOp = node->getOp(); - reduceComparison = false; - switch (node->getOp()) { - case glslang::EOpVectorEqual: binOp = glslang::EOpVectorEqual; break; - case glslang::EOpVectorNotEqual: binOp = glslang::EOpVectorNotEqual; break; - default: binOp = node->getOp(); break; - } - - break; - } - case glslang::EOpMul: - // component-wise matrix multiply - binOp = glslang::EOpMul; - break; - case glslang::EOpOuterProduct: - // two vectors multiplied to make a matrix - binOp = glslang::EOpOuterProduct; - break; - case glslang::EOpDot: - { - // for scalar dot product, use multiply - glslang::TIntermSequence& glslangOperands = node->getSequence(); - if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1) - binOp = glslang::EOpMul; - break; - } - case glslang::EOpMod: - // when an aggregate, this is the floating-point mod built-in function, - // which can be emitted by the one in createBinaryOperation() - binOp = glslang::EOpMod; - break; - - case glslang::EOpEmitVertex: - case glslang::EOpEndPrimitive: - case glslang::EOpBarrier: - case glslang::EOpMemoryBarrier: - case glslang::EOpMemoryBarrierAtomicCounter: - case glslang::EOpMemoryBarrierBuffer: - case glslang::EOpMemoryBarrierImage: - case glslang::EOpMemoryBarrierShared: - case glslang::EOpGroupMemoryBarrier: - case glslang::EOpDeviceMemoryBarrier: - case glslang::EOpAllMemoryBarrierWithGroupSync: - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - case glslang::EOpWorkgroupMemoryBarrier: - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - case glslang::EOpSubgroupBarrier: - case glslang::EOpSubgroupMemoryBarrier: - case glslang::EOpSubgroupMemoryBarrierBuffer: - case glslang::EOpSubgroupMemoryBarrierImage: - case glslang::EOpSubgroupMemoryBarrierShared: - noReturnValue = true; - // These all have 0 operands and will naturally finish up in the code below for 0 operands - break; - - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicSubtract: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - atomic = true; - break; - - case glslang::EOpAtomicStore: - noReturnValue = true; - [[fallthrough]]; - case glslang::EOpAtomicLoad: - atomic = true; - break; - - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - builder.addExtension("SPV_KHR_shader_atomic_counter_ops"); - builder.addCapability(spv::CapabilityAtomicStorageOps); - atomic = true; - break; - - case glslang::EOpAbsDifference: - case glslang::EOpAddSaturate: - case glslang::EOpSubSaturate: - case glslang::EOpAverage: - case glslang::EOpAverageRounded: - case glslang::EOpMul32x16: - builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); - builder.addExtension("SPV_INTEL_shader_integer_functions2"); - binOp = node->getOp(); - break; - - case glslang::EOpExpectEXT: - builder.addCapability(spv::CapabilityExpectAssumeKHR); - builder.addExtension(spv::E_SPV_KHR_expect_assume); - binOp = node->getOp(); - break; - - case glslang::EOpIgnoreIntersectionNV: - case glslang::EOpTerminateRayNV: - case glslang::EOpTraceNV: - case glslang::EOpTraceRayMotionNV: - case glslang::EOpTraceKHR: - case glslang::EOpExecuteCallableNV: - case glslang::EOpExecuteCallableKHR: - case glslang::EOpWritePackedPrimitiveIndices4x8NV: - case glslang::EOpEmitMeshTasksEXT: - case glslang::EOpSetMeshOutputsEXT: - noReturnValue = true; - break; - case glslang::EOpRayQueryInitialize: - case glslang::EOpRayQueryTerminate: - case glslang::EOpRayQueryGenerateIntersection: - case glslang::EOpRayQueryConfirmIntersection: - builder.addExtension("SPV_KHR_ray_query"); - builder.addCapability(spv::CapabilityRayQueryKHR); - noReturnValue = true; - break; - case glslang::EOpRayQueryProceed: - case glslang::EOpRayQueryGetIntersectionType: - case glslang::EOpRayQueryGetRayTMin: - case glslang::EOpRayQueryGetRayFlags: - case glslang::EOpRayQueryGetIntersectionT: - case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: - case glslang::EOpRayQueryGetIntersectionInstanceId: - case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: - case glslang::EOpRayQueryGetIntersectionGeometryIndex: - case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: - case glslang::EOpRayQueryGetIntersectionBarycentrics: - case glslang::EOpRayQueryGetIntersectionFrontFace: - case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: - case glslang::EOpRayQueryGetIntersectionObjectRayDirection: - case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: - case glslang::EOpRayQueryGetWorldRayDirection: - case glslang::EOpRayQueryGetWorldRayOrigin: - case glslang::EOpRayQueryGetIntersectionObjectToWorld: - case glslang::EOpRayQueryGetIntersectionWorldToObject: - builder.addExtension("SPV_KHR_ray_query"); - builder.addCapability(spv::CapabilityRayQueryKHR); - break; - case glslang::EOpCooperativeMatrixLoad: - case glslang::EOpCooperativeMatrixStore: - case glslang::EOpCooperativeMatrixLoadNV: - case glslang::EOpCooperativeMatrixStoreNV: - case glslang::EOpCooperativeMatrixLoadTensorNV: - case glslang::EOpCooperativeMatrixStoreTensorNV: - case glslang::EOpCooperativeMatrixReduceNV: - case glslang::EOpCooperativeMatrixPerElementOpNV: - case glslang::EOpCooperativeMatrixTransposeNV: - noReturnValue = true; - break; - case glslang::EOpBeginInvocationInterlock: - case glslang::EOpEndInvocationInterlock: - builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); - noReturnValue = true; - break; - - case glslang::EOpHitObjectTraceRayNV: - case glslang::EOpHitObjectTraceRayMotionNV: - case glslang::EOpHitObjectGetAttributesNV: - case glslang::EOpHitObjectExecuteShaderNV: - case glslang::EOpHitObjectRecordEmptyNV: - case glslang::EOpHitObjectRecordMissNV: - case glslang::EOpHitObjectRecordMissMotionNV: - case glslang::EOpHitObjectRecordHitNV: - case glslang::EOpHitObjectRecordHitMotionNV: - case glslang::EOpHitObjectRecordHitWithIndexNV: - case glslang::EOpHitObjectRecordHitWithIndexMotionNV: - case glslang::EOpReorderThreadNV: - noReturnValue = true; - [[fallthrough]]; - case glslang::EOpHitObjectIsEmptyNV: - case glslang::EOpHitObjectIsMissNV: - case glslang::EOpHitObjectIsHitNV: - case glslang::EOpHitObjectGetRayTMinNV: - case glslang::EOpHitObjectGetRayTMaxNV: - case glslang::EOpHitObjectGetObjectRayOriginNV: - case glslang::EOpHitObjectGetObjectRayDirectionNV: - case glslang::EOpHitObjectGetWorldRayOriginNV: - case glslang::EOpHitObjectGetWorldRayDirectionNV: - case glslang::EOpHitObjectGetObjectToWorldNV: - case glslang::EOpHitObjectGetWorldToObjectNV: - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - case glslang::EOpHitObjectGetInstanceIdNV: - case glslang::EOpHitObjectGetGeometryIndexNV: - case glslang::EOpHitObjectGetPrimitiveIndexNV: - case glslang::EOpHitObjectGetHitKindNV: - case glslang::EOpHitObjectGetCurrentTimeNV: - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - builder.addExtension(spv::E_SPV_NV_shader_invocation_reorder); - builder.addCapability(spv::CapabilityShaderInvocationReorderNV); - break; - case glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: - builder.addExtension(spv::E_SPV_KHR_ray_tracing_position_fetch); - builder.addCapability(spv::CapabilityRayQueryPositionFetchKHR); - noReturnValue = true; - break; - - case glslang::EOpImageSampleWeightedQCOM: - builder.addCapability(spv::CapabilityTextureSampleWeightedQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - break; - case glslang::EOpImageBoxFilterQCOM: - builder.addCapability(spv::CapabilityTextureBoxFilterQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - break; - case glslang::EOpImageBlockMatchSADQCOM: - case glslang::EOpImageBlockMatchSSDQCOM: - builder.addCapability(spv::CapabilityTextureBlockMatchQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - break; - - case glslang::EOpImageBlockMatchWindowSSDQCOM: - case glslang::EOpImageBlockMatchWindowSADQCOM: - builder.addCapability(spv::CapabilityTextureBlockMatchQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - builder.addCapability(spv::CapabilityTextureBlockMatch2QCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing2); - break; - - case glslang::EOpImageBlockMatchGatherSSDQCOM: - case glslang::EOpImageBlockMatchGatherSADQCOM: - builder.addCapability(spv::CapabilityTextureBlockMatchQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - builder.addCapability(spv::CapabilityTextureBlockMatch2QCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing2); - break; - - case glslang::EOpFetchMicroTriangleVertexPositionNV: - case glslang::EOpFetchMicroTriangleVertexBarycentricNV: - builder.addExtension(spv::E_SPV_NV_displacement_micromap); - builder.addCapability(spv::CapabilityDisplacementMicromapNV); - break; - - case glslang::EOpDebugPrintf: - noReturnValue = true; - break; - - default: - break; - } - - // - // See if it maps to a regular operation. - // - if (binOp != glslang::EOpNull) { - glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped(); - glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped(); - assert(left && right); - - builder.clearAccessChain(); - left->traverse(this); - spv::Id leftId = accessChainLoad(left->getType()); - - builder.clearAccessChain(); - right->traverse(this); - spv::Id rightId = accessChainLoad(right->getType()); - - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - OpDecorations decorations = { precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - result = createBinaryOperation(binOp, decorations, - resultType(), leftId, rightId, - left->getType().getBasicType(), reduceComparison); - - // code above should only make binOp that exists in createBinaryOperation - assert(result != spv::NoResult); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; - } - - // - // Create the list of operands. - // - glslang::TIntermSequence& glslangOperands = node->getSequence(); - std::vector operands; - std::vector memoryAccessOperands; - for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) { - // special case l-value operands; there are just a few - bool lvalue = false; - switch (node->getOp()) { - case glslang::EOpModf: - if (arg == 1) - lvalue = true; - break; - - - - case glslang::EOpHitObjectRecordHitNV: - case glslang::EOpHitObjectRecordHitMotionNV: - case glslang::EOpHitObjectRecordHitWithIndexNV: - case glslang::EOpHitObjectRecordHitWithIndexMotionNV: - case glslang::EOpHitObjectTraceRayNV: - case glslang::EOpHitObjectTraceRayMotionNV: - case glslang::EOpHitObjectExecuteShaderNV: - case glslang::EOpHitObjectRecordMissNV: - case glslang::EOpHitObjectRecordMissMotionNV: - case glslang::EOpHitObjectGetAttributesNV: - if (arg == 0) - lvalue = true; - break; - - case glslang::EOpRayQueryInitialize: - case glslang::EOpRayQueryTerminate: - case glslang::EOpRayQueryConfirmIntersection: - case glslang::EOpRayQueryProceed: - case glslang::EOpRayQueryGenerateIntersection: - case glslang::EOpRayQueryGetIntersectionType: - case glslang::EOpRayQueryGetIntersectionT: - case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: - case glslang::EOpRayQueryGetIntersectionInstanceId: - case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: - case glslang::EOpRayQueryGetIntersectionGeometryIndex: - case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: - case glslang::EOpRayQueryGetIntersectionBarycentrics: - case glslang::EOpRayQueryGetIntersectionFrontFace: - case glslang::EOpRayQueryGetIntersectionObjectRayDirection: - case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: - case glslang::EOpRayQueryGetIntersectionObjectToWorld: - case glslang::EOpRayQueryGetIntersectionWorldToObject: - if (arg == 0) - lvalue = true; - break; - - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicSubtract: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - if (arg == 0) - lvalue = true; - break; - - case glslang::EOpFrexp: - if (arg == 1) - lvalue = true; - break; - case glslang::EOpInterpolateAtSample: - case glslang::EOpInterpolateAtOffset: - case glslang::EOpInterpolateAtVertex: - if (arg == 0) { - // If GLSL, use the address of the interpolant argument. - // If HLSL, use an internal version of OpInterolates that takes - // the rvalue of the interpolant. A fixup pass in spirv-opt - // legalization will remove the OpLoad and convert to an lvalue. - // Had to do this because legalization will only propagate a - // builtin into an rvalue. - lvalue = glslangIntermediate->getSource() != glslang::EShSourceHlsl; - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - // That is, we transform - // - // interpolate(v.zy) -> interpolate(v).zy - // - if (glslangOperands[0]->getAsOperator() && - glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - invertedType = convertGlslangToSpvType( - glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); - } - break; - case glslang::EOpAtomicLoad: - case glslang::EOpAtomicStore: - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - if (arg == 0) - lvalue = true; - break; - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - if (arg == 2) - lvalue = true; - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - if (arg >= 2) - lvalue = true; - break; - case glslang::EOpCooperativeMatrixLoad: - case glslang::EOpCooperativeMatrixLoadNV: - case glslang::EOpCooperativeMatrixLoadTensorNV: - if (arg == 0 || arg == 1) - lvalue = true; - break; - case glslang::EOpCooperativeMatrixStore: - case glslang::EOpCooperativeMatrixStoreNV: - case glslang::EOpCooperativeMatrixStoreTensorNV: - if (arg == 1) - lvalue = true; - break; - case glslang::EOpCooperativeMatrixReduceNV: - case glslang::EOpCooperativeMatrixPerElementOpNV: - case glslang::EOpCooperativeMatrixTransposeNV: - if (arg == 0) - lvalue = true; - break; - case glslang::EOpSpirvInst: - if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvByReference()) - lvalue = true; - break; - case glslang::EOpReorderThreadNV: - //Three variants of reorderThreadNV, two of them use hitObjectNV - if (arg == 0 && glslangOperands.size() != 2) - lvalue = true; - break; - case glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: - if (arg == 0 || arg == 2) - lvalue = true; - break; - default: - break; - } - builder.clearAccessChain(); - if (invertedType != spv::NoType && arg == 0) - glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this); - else - glslangOperands[arg]->traverse(this); - - if (node->getOp() == glslang::EOpCooperativeMatrixLoad || - node->getOp() == glslang::EOpCooperativeMatrixStore || - node->getOp() == glslang::EOpCooperativeMatrixLoadNV || - node->getOp() == glslang::EOpCooperativeMatrixStoreNV || - node->getOp() == glslang::EOpCooperativeMatrixLoadTensorNV || - node->getOp() == glslang::EOpCooperativeMatrixStoreTensorNV) { - - if (arg == 1) { - // fold "element" parameter into the access chain - spv::Builder::AccessChain save = builder.getAccessChain(); - builder.clearAccessChain(); - glslangOperands[2]->traverse(this); - - spv::Id elementId = accessChainLoad(glslangOperands[2]->getAsTyped()->getType()); - - builder.setAccessChain(save); - - // Point to the first element of the array. - builder.accessChainPush(elementId, - TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()), - glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment()); - - spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; - unsigned int alignment = builder.getAccessChain().alignment; - - int memoryAccess = TranslateMemoryAccess(coherentFlags); - if (node->getOp() == glslang::EOpCooperativeMatrixLoad || - node->getOp() == glslang::EOpCooperativeMatrixLoadNV || - node->getOp() == glslang::EOpCooperativeMatrixLoadTensorNV) - memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask; - if (node->getOp() == glslang::EOpCooperativeMatrixStore || - node->getOp() == glslang::EOpCooperativeMatrixStoreNV || - node->getOp() == glslang::EOpCooperativeMatrixStoreTensorNV) - memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask; - if (builder.getStorageClass(builder.getAccessChain().base) == - spv::StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - memoryAccessOperands.push_back(spv::IdImmediate(false, memoryAccess)); - - if (memoryAccess & spv::MemoryAccessAlignedMask) { - memoryAccessOperands.push_back(spv::IdImmediate(false, alignment)); - } - - if (memoryAccess & - (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) { - memoryAccessOperands.push_back(spv::IdImmediate(true, - builder.makeUintConstant(TranslateMemoryScope(coherentFlags)))); - } - } else if (arg == 2) { - continue; - } - } - - // for l-values, pass the address, for r-values, pass the value - if (lvalue) { - if (invertedType == spv::NoType && !builder.isSpvLvalue()) { - // SPIR-V cannot represent an l-value containing a swizzle that doesn't - // reduce to a simple access chain. So, we need a temporary vector to - // receive the result, and must later swizzle that into the original - // l-value. - complexLvalues.push_back(builder.getAccessChain()); - temporaryLvalues.push_back(builder.createVariable( - spv::NoPrecision, spv::StorageClassFunction, - builder.accessChainGetInferredType(), "swizzleTemp")); - operands.push_back(temporaryLvalues.back()); - } else { - operands.push_back(builder.accessChainGetLValue()); - } - lvalueCoherentFlags = builder.getAccessChain().coherentFlags; - lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()); - } else { - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - glslang::TOperator glslangOp = node->getOp(); - if (arg == 1 && - (glslangOp == glslang::EOpRayQueryGetIntersectionType || - glslangOp == glslang::EOpRayQueryGetIntersectionT || - glslangOp == glslang::EOpRayQueryGetIntersectionInstanceCustomIndex || - glslangOp == glslang::EOpRayQueryGetIntersectionInstanceId || - glslangOp == glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset || - glslangOp == glslang::EOpRayQueryGetIntersectionGeometryIndex || - glslangOp == glslang::EOpRayQueryGetIntersectionPrimitiveIndex || - glslangOp == glslang::EOpRayQueryGetIntersectionBarycentrics || - glslangOp == glslang::EOpRayQueryGetIntersectionFrontFace || - glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayDirection || - glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayOrigin || - glslangOp == glslang::EOpRayQueryGetIntersectionObjectToWorld || - glslangOp == glslang::EOpRayQueryGetIntersectionWorldToObject || - glslangOp == glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT - )) { - bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst(); - operands.push_back(builder.makeIntConstant(cond ? 1 : 0)); - } else if ((arg == 10 && glslangOp == glslang::EOpTraceKHR) || - (arg == 11 && glslangOp == glslang::EOpTraceRayMotionNV) || - (arg == 1 && glslangOp == glslang::EOpExecuteCallableKHR) || - (arg == 1 && glslangOp == glslang::EOpHitObjectExecuteShaderNV) || - (arg == 11 && glslangOp == glslang::EOpHitObjectTraceRayNV) || - (arg == 12 && glslangOp == glslang::EOpHitObjectTraceRayMotionNV)) { - const int set = glslangOp == glslang::EOpExecuteCallableKHR ? 1 : 0; - const int location = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getUConst(); - auto itNode = locationToSymbol[set].find(location); - visitSymbol(itNode->second); - spv::Id symId = getSymbolId(itNode->second); - operands.push_back(symId); - } else if ((arg == 12 && glslangOp == glslang::EOpHitObjectRecordHitNV) || - (arg == 13 && glslangOp == glslang::EOpHitObjectRecordHitMotionNV) || - (arg == 11 && glslangOp == glslang::EOpHitObjectRecordHitWithIndexNV) || - (arg == 12 && glslangOp == glslang::EOpHitObjectRecordHitWithIndexMotionNV) || - (arg == 1 && glslangOp == glslang::EOpHitObjectGetAttributesNV)) { - const int location = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getUConst(); - const int set = 2; - auto itNode = locationToSymbol[set].find(location); - visitSymbol(itNode->second); - spv::Id symId = getSymbolId(itNode->second); - operands.push_back(symId); - } else if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Will be translated to a literal value, make a placeholder here - operands.push_back(spv::NoResult); - } else if (glslangOperands[arg]->getAsTyped()->getBasicType() == glslang::EbtFunction) { - spv::Function* function = functionMap[glslangOperands[arg]->getAsSymbolNode()->getMangledName().c_str()]; - assert(function); - operands.push_back(function->getId()); - } else { - operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); - } - } - } - - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - if (node->getOp() == glslang::EOpCooperativeMatrixLoadTensorNV) { - std::vector idImmOps; - - builder.addCapability(spv::CapabilityCooperativeMatrixTensorAddressingNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); - - spv::Id object = builder.createLoad(operands[0], spv::NoPrecision); - - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // Pointer - idImmOps.push_back(spv::IdImmediate(true, object)); // Object - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // tensorLayout - - idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end()); // memoryaccess - - // initialize tensor operands to zero, then OR in flags based on the operands - size_t tensorOpIdx = idImmOps.size(); - idImmOps.push_back(spv::IdImmediate(false, 0)); - - for (uint32_t i = 3; i < operands.size(); ++i) { - if (builder.isTensorView(operands[i])) { - idImmOps[tensorOpIdx].word |= spv::TensorAddressingOperandsTensorViewMask; - } else { - // must be the decode func - idImmOps[tensorOpIdx].word |= spv::TensorAddressingOperandsDecodeFuncMask; - builder.addCapability(spv::CapabilityCooperativeMatrixBlockLoadsNV); - } - idImmOps.push_back(spv::IdImmediate(true, operands[i])); // tensorView or decodeFunc - } - - // get the pointee type - spv::Id typeId = builder.getContainedTypeId(builder.getTypeId(operands[0])); - assert(builder.isCooperativeMatrixType(typeId)); - // do the op - spv::Id result = builder.createOp(spv::OpCooperativeMatrixLoadTensorNV, typeId, idImmOps); - // store the result to the pointer (out param 'm') - builder.createStore(result, operands[0]); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixLoad || - node->getOp() == glslang::EOpCooperativeMatrixLoadNV) { - std::vector idImmOps; - - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf - if (node->getOp() == glslang::EOpCooperativeMatrixLoad) { - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // matrixLayout - auto layout = builder.getConstantScalar(operands[3]); - if (layout == spv::CooperativeMatrixLayoutRowBlockedInterleavedARM || - layout == spv::CooperativeMatrixLayoutColumnBlockedInterleavedARM) { - builder.addExtension(spv::E_SPV_ARM_cooperative_matrix_layouts); - builder.addCapability(spv::CapabilityCooperativeMatrixLayoutsARM); - } - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - } else { - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // colMajor - } - idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end()); - // get the pointee type - spv::Id typeId = builder.getContainedTypeId(builder.getTypeId(operands[0])); - assert(builder.isCooperativeMatrixType(typeId)); - // do the op - spv::Id result = node->getOp() == glslang::EOpCooperativeMatrixLoad - ? builder.createOp(spv::OpCooperativeMatrixLoadKHR, typeId, idImmOps) - : builder.createOp(spv::OpCooperativeMatrixLoadNV, typeId, idImmOps); - // store the result to the pointer (out param 'm') - builder.createStore(result, operands[0]); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixStoreTensorNV) { - std::vector idImmOps; - - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf - idImmOps.push_back(spv::IdImmediate(true, operands[0])); // object - - builder.addCapability(spv::CapabilityCooperativeMatrixTensorAddressingNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); - - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // tensorLayout - - idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end()); // memoryaccess - - if (operands.size() > 3) { - idImmOps.push_back(spv::IdImmediate(false, spv::TensorAddressingOperandsTensorViewMask)); - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // tensorView - } else { - idImmOps.push_back(spv::IdImmediate(false, 0)); - } - - builder.createNoResultOp(spv::OpCooperativeMatrixStoreTensorNV, idImmOps); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixStore || - node->getOp() == glslang::EOpCooperativeMatrixStoreNV) { - std::vector idImmOps; - - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf - idImmOps.push_back(spv::IdImmediate(true, operands[0])); // object - if (node->getOp() == glslang::EOpCooperativeMatrixStore) { - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // matrixLayout - auto layout = builder.getConstantScalar(operands[3]); - if (layout == spv::CooperativeMatrixLayoutRowBlockedInterleavedARM || - layout == spv::CooperativeMatrixLayoutColumnBlockedInterleavedARM) { - builder.addExtension(spv::E_SPV_ARM_cooperative_matrix_layouts); - builder.addCapability(spv::CapabilityCooperativeMatrixLayoutsARM); - } - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - } else { - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // colMajor - } - idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end()); - - if (node->getOp() == glslang::EOpCooperativeMatrixStore) - builder.createNoResultOp(spv::OpCooperativeMatrixStoreKHR, idImmOps); - else - builder.createNoResultOp(spv::OpCooperativeMatrixStoreNV, idImmOps); - result = 0; - } else if (node->getOp() == glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT) { - std::vector idImmOps; - - idImmOps.push_back(spv::IdImmediate(true, operands[0])); // q - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // committed - - spv::Id typeId = builder.makeArrayType(builder.makeVectorType(builder.makeFloatType(32), 3), - builder.makeUintConstant(3), 0); - // do the op - - spv::Op spvOp = spv::OpRayQueryGetIntersectionTriangleVertexPositionsKHR; - - spv::Id result = builder.createOp(spvOp, typeId, idImmOps); - // store the result to the pointer (out param 'm') - builder.createStore(result, operands[2]); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixMulAdd) { - uint32_t matrixOperands = 0; - - // If the optional operand is present, initialize matrixOperands to that value. - if (glslangOperands.size() == 4 && glslangOperands[3]->getAsConstantUnion()) { - matrixOperands = glslangOperands[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - } - - // Determine Cooperative Matrix Operands bits from the signedness of the types. - if (isTypeSignedInt(glslangOperands[0]->getAsTyped()->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixASignedComponentsKHRMask; - if (isTypeSignedInt(glslangOperands[1]->getAsTyped()->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixBSignedComponentsKHRMask; - if (isTypeSignedInt(glslangOperands[2]->getAsTyped()->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixCSignedComponentsKHRMask; - if (isTypeSignedInt(node->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask; - - std::vector idImmOps; - idImmOps.push_back(spv::IdImmediate(true, operands[0])); - idImmOps.push_back(spv::IdImmediate(true, operands[1])); - idImmOps.push_back(spv::IdImmediate(true, operands[2])); - if (matrixOperands != 0) - idImmOps.push_back(spv::IdImmediate(false, matrixOperands)); - - result = builder.createOp(spv::OpCooperativeMatrixMulAddKHR, resultType(), idImmOps); - } else if (node->getOp() == glslang::EOpCooperativeMatrixReduceNV) { - builder.addCapability(spv::CapabilityCooperativeMatrixReductionsNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); - - spv::Op opcode = spv::OpCooperativeMatrixReduceNV; - unsigned mask = glslangOperands[2]->getAsConstantUnion()->getConstArray()[0].getUConst(); - - spv::Id typeId = builder.getContainedTypeId(builder.getTypeId(operands[0])); - assert(builder.isCooperativeMatrixType(typeId)); - - result = builder.createCooperativeMatrixReduce(opcode, typeId, operands[1], mask, operands[3]); - // store the result to the pointer (out param 'm') - builder.createStore(result, operands[0]); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixPerElementOpNV) { - builder.addCapability(spv::CapabilityCooperativeMatrixPerElementOperationsNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); - - spv::Id typeId = builder.getContainedTypeId(builder.getTypeId(operands[0])); - assert(builder.isCooperativeMatrixType(typeId)); - - result = builder.createCooperativeMatrixPerElementOp(typeId, operands); - // store the result to the pointer - builder.createStore(result, operands[0]); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixTransposeNV) { - - builder.addCapability(spv::CapabilityCooperativeMatrixConversionsNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix2); - - spv::Id typeId = builder.getContainedTypeId(builder.getTypeId(operands[0])); - assert(builder.isCooperativeMatrixType(typeId)); - - result = builder.createUnaryOp(spv::OpCooperativeMatrixTransposeNV, typeId, operands[1]); - // store the result to the pointer - builder.createStore(result, operands[0]); - result = 0; - } else if (atomic) { - // Handle all atomics - glslang::TBasicType typeProxy = (node->getOp() == glslang::EOpAtomicStore) - ? node->getSequence()[0]->getAsTyped()->getBasicType() : node->getBasicType(); - result = createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy, - lvalueCoherentFlags, node->getType()); - } else if (node->getOp() == glslang::EOpSpirvInst) { - const auto& spirvInst = node->getSpirvInstruction(); - if (spirvInst.set == "") { - std::vector idImmOps; - for (unsigned int i = 0; i < glslangOperands.size(); ++i) { - if (glslangOperands[i]->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Translate the constant to a literal value - std::vector literals; - glslang::TVector constants; - constants.push_back(glslangOperands[i]->getAsConstantUnion()); - TranslateLiterals(constants, literals); - idImmOps.push_back({false, literals[0]}); - } else - idImmOps.push_back({true, operands[i]}); - } - - if (node->getBasicType() == glslang::EbtVoid) - builder.createNoResultOp(static_cast(spirvInst.id), idImmOps); - else - result = builder.createOp(static_cast(spirvInst.id), resultType(), idImmOps); - } else { - result = builder.createBuiltinCall( - resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()), - spirvInst.id, operands); - } - noReturnValue = node->getBasicType() == glslang::EbtVoid; - } else if (node->getOp() == glslang::EOpDebugPrintf) { - if (!nonSemanticDebugPrintf) { - nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf"); - } - result = builder.createBuiltinCall(builder.makeVoidType(), nonSemanticDebugPrintf, spv::NonSemanticDebugPrintfDebugPrintf, operands); - builder.addExtension(spv::E_SPV_KHR_non_semantic_info); - } else { - // Pass through to generic operations. - switch (glslangOperands.size()) { - case 0: - result = createNoArgOperation(node->getOp(), precision, resultType()); - break; - case 1: - { - OpDecorations decorations = { precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - result = createUnaryOperation( - node->getOp(), decorations, - resultType(), operands.front(), - glslangOperands[0]->getAsTyped()->getBasicType(), lvalueCoherentFlags, node->getType()); - } - break; - default: - result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - break; - } - - if (invertedType != spv::NoResult) - result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result); - - for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) { - builder.setAccessChain(complexLvalues[i]); - builder.accessChainStore(builder.createLoad(temporaryLvalues[i], spv::NoPrecision), - TranslateNonUniformDecoration(complexLvalues[i].coherentFlags)); - } - } - - if (noReturnValue) - return false; - - if (! result) { - logger->missingFunctionality("unknown glslang aggregate"); - return true; // pick up a child as a placeholder operand - } else { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - return false; - } -} - -// This path handles both if-then-else and ?: -// The if-then-else has a node type of void, while -// ?: has either a void or a non-void node type -// -// Leaving the result, when not void: -// GLSL only has r-values as the result of a :?, but -// if we have an l-value, that can be more efficient if it will -// become the base of a complex r-value expression, because the -// next layer copies r-values into memory to use the access-chain mechanism -bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node) -{ - // see if OpSelect can handle it - const auto isOpSelectable = [&]() { - if (node->getBasicType() == glslang::EbtVoid) - return false; - // OpSelect can do all other types starting with SPV 1.4 - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4) { - // pre-1.4, only scalars and vectors can be handled - if ((!node->getType().isScalar() && !node->getType().isVector())) - return false; - } - return true; - }; - - // See if it simple and safe, or required, to execute both sides. - // Crucially, side effects must be either semantically required or avoided, - // and there are performance trade-offs. - // Return true if required or a good idea (and safe) to execute both sides, - // false otherwise. - const auto bothSidesPolicy = [&]() -> bool { - // do we have both sides? - if (node->getTrueBlock() == nullptr || - node->getFalseBlock() == nullptr) - return false; - - // required? (unless we write additional code to look for side effects - // and make performance trade-offs if none are present) - if (!node->getShortCircuit()) - return true; - - // if not required to execute both, decide based on performance/practicality... - - if (!isOpSelectable()) - return false; - - assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() && - node->getType() == node->getFalseBlock()->getAsTyped()->getType()); - - // return true if a single operand to ? : is okay for OpSelect - const auto operandOkay = [](glslang::TIntermTyped* node) { - return node->getAsSymbolNode() || node->getType().getQualifier().isConstant(); - }; - - return operandOkay(node->getTrueBlock() ->getAsTyped()) && - operandOkay(node->getFalseBlock()->getAsTyped()); - }; - - spv::Id result = spv::NoResult; // upcoming result selecting between trueValue and falseValue - // emit the condition before doing anything with selection - node->getCondition()->traverse(this); - spv::Id condition = accessChainLoad(node->getCondition()->getType()); - - // Find a way of executing both sides and selecting the right result. - const auto executeBothSides = [&]() -> void { - // execute both sides - spv::Id resultType = convertGlslangToSpvType(node->getType()); - node->getTrueBlock()->traverse(this); - spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - node->getFalseBlock()->traverse(this); - spv::Id falseValue = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()); - - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - - // done if void - if (node->getBasicType() == glslang::EbtVoid) - return; - - // emit code to select between trueValue and falseValue - // see if OpSelect can handle the result type, and that the SPIR-V types - // of the inputs match the result type. - if (isOpSelectable()) { - // Emit OpSelect for this selection. - - // smear condition to vector, if necessary (AST is always scalar) - // Before 1.4, smear like for mix(), starting with 1.4, keep it scalar - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) { - condition = builder.smearScalar(spv::NoPrecision, condition, - builder.makeVectorType(builder.makeBoolType(), - builder.getNumComponents(trueValue))); - } - - // If the types do not match, it is because of mismatched decorations on aggregates. - // Since isOpSelectable only lets us get here for SPIR-V >= 1.4, we can use OpCopyObject - // to get matching types. - if (builder.getTypeId(trueValue) != resultType) { - trueValue = builder.createUnaryOp(spv::OpCopyLogical, resultType, trueValue); - } - if (builder.getTypeId(falseValue) != resultType) { - falseValue = builder.createUnaryOp(spv::OpCopyLogical, resultType, falseValue); - } - - // OpSelect - result = builder.createTriOp(spv::OpSelect, resultType, condition, trueValue, falseValue); - - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } else { - // We need control flow to select the result. - // TODO: Once SPIR-V OpSelect allows arbitrary types, eliminate this path. - result = builder.createVariable(TranslatePrecisionDecoration(node->getType()), - spv::StorageClassFunction, resultType); - - // Selection control: - const spv::SelectionControlMask control = TranslateSelectionControl(*node); - - // make an "if" based on the value created by the condition - spv::Builder::If ifBuilder(condition, control, builder); - - // emit the "then" statement - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), trueValue); - - ifBuilder.makeBeginElse(); - // emit the "else" statement - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), falseValue); - - // finish off the control flow - ifBuilder.makeEndIf(); - - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - } - }; - - // Execute the one side needed, as per the condition - const auto executeOneSide = [&]() { - // Always emit control flow. - if (node->getBasicType() != glslang::EbtVoid) { - result = builder.createVariable(TranslatePrecisionDecoration(node->getType()), spv::StorageClassFunction, - convertGlslangToSpvType(node->getType())); - } - - // Selection control: - const spv::SelectionControlMask control = TranslateSelectionControl(*node); - - // make an "if" based on the value created by the condition - spv::Builder::If ifBuilder(condition, control, builder); - - // emit the "then" statement - if (node->getTrueBlock() != nullptr) { - node->getTrueBlock()->traverse(this); - if (result != spv::NoResult) { - spv::Id load = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), load); - } - } - - if (node->getFalseBlock() != nullptr) { - ifBuilder.makeBeginElse(); - // emit the "else" statement - node->getFalseBlock()->traverse(this); - if (result != spv::NoResult) { - spv::Id load = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()); - - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), load); - } - } - - // finish off the control flow - ifBuilder.makeEndIf(); - - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - } - }; - - // Try for OpSelect (or a requirement to execute both sides) - if (bothSidesPolicy()) { - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - executeBothSides(); - } else - executeOneSide(); - - return false; -} - -bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::TIntermSwitch* node) -{ - // emit and get the condition before doing anything with switch - node->getCondition()->traverse(this); - spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType()); - - // Selection control: - const spv::SelectionControlMask control = TranslateSwitchControl(*node); - - // browse the children to sort out code segments - int defaultSegment = -1; - std::vector codeSegments; - glslang::TIntermSequence& sequence = node->getBody()->getSequence(); - std::vector caseValues; - std::vector valueIndexToSegment(sequence.size()); // note: probably not all are used, it is an overestimate - for (glslang::TIntermSequence::iterator c = sequence.begin(); c != sequence.end(); ++c) { - TIntermNode* child = *c; - if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpDefault) - defaultSegment = (int)codeSegments.size(); - else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) { - valueIndexToSegment[caseValues.size()] = (int)codeSegments.size(); - caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion() - ->getConstArray()[0].getIConst()); - } else - codeSegments.push_back(child); - } - - // handle the case where the last code segment is missing, due to no code - // statements between the last case and the end of the switch statement - if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) || - (int)codeSegments.size() == defaultSegment) - codeSegments.push_back(nullptr); - - // make the switch statement - std::vector segmentBlocks; // returned, as the blocks allocated in the call - builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, - segmentBlocks); - - // emit all the code in the segments - breakForLoop.push(false); - for (unsigned int s = 0; s < codeSegments.size(); ++s) { - builder.nextSwitchSegment(segmentBlocks, s); - if (codeSegments[s]) - codeSegments[s]->traverse(this); - else - builder.addSwitchBreak(true); - } - breakForLoop.pop(); - - builder.endSwitch(segmentBlocks); - - return false; -} - -void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node) -{ - if (node->getQualifier().isSpirvLiteral()) - return; // Translated to a literal value, skip further processing - - int nextConst = 0; - spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false); - - builder.clearAccessChain(); - builder.setAccessChainRValue(constant); -} - -bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node) -{ - auto blocks = builder.makeNewLoop(); - builder.createBranch(true, &blocks.head); - - // Loop control: - std::vector operands; - const spv::LoopControlMask control = TranslateLoopControl(*node, operands); - - // Spec requires back edges to target header blocks, and every header block - // must dominate its merge block. Make a header block first to ensure these - // conditions are met. By definition, it will contain OpLoopMerge, followed - // by a block-ending branch. But we don't want to put any other body/test - // instructions in it, since the body/test may have arbitrary instructions, - // including merges of its own. - builder.setBuildPoint(&blocks.head); - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands); - if (node->testFirst() && node->getTest()) { - spv::Block& test = builder.makeNewBlock(); - builder.createBranch(true, &test); - - builder.setBuildPoint(&test); - node->getTest()->traverse(this); - spv::Id condition = accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.body, &blocks.merge); - - builder.setBuildPoint(&blocks.body); - breakForLoop.push(true); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(true, &blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - builder.createBranch(true, &blocks.head); - } else { - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - builder.createBranch(true, &blocks.body); - - breakForLoop.push(true); - builder.setBuildPoint(&blocks.body); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(true, &blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - if (node->getTest()) { - node->getTest()->traverse(this); - spv::Id condition = - accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.head, &blocks.merge); - } else { - // TODO: unless there was a break/return/discard instruction - // somewhere in the body, this is an infinite loop, so we should - // issue a warning. - builder.createBranch(true, &blocks.head); - } - } - builder.setBuildPoint(&blocks.merge); - builder.closeLoop(); - return false; -} - -bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::TIntermBranch* node) -{ - if (node->getExpression()) - node->getExpression()->traverse(this); - - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - - switch (node->getFlowOp()) { - case glslang::EOpKill: - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) { - builder.addCapability(spv::CapabilityDemoteToHelperInvocation); - builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT); - } else { - builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation"); - } - } else { - builder.makeStatementTerminator(spv::OpKill, "post-discard"); - } - break; - case glslang::EOpTerminateInvocation: - builder.addExtension(spv::E_SPV_KHR_terminate_invocation); - builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation"); - break; - case glslang::EOpBreak: - if (breakForLoop.top()) - builder.createLoopExit(); - else - builder.addSwitchBreak(false); - break; - case glslang::EOpContinue: - builder.createLoopContinue(); - break; - case glslang::EOpReturn: - if (node->getExpression() != nullptr) { - const glslang::TType& glslangReturnType = node->getExpression()->getType(); - spv::Id returnId = accessChainLoad(glslangReturnType); - if (builder.getTypeId(returnId) != currentFunction->getReturnType() || - TranslatePrecisionDecoration(glslangReturnType) != currentFunction->getReturnPrecision()) { - builder.clearAccessChain(); - spv::Id copyId = builder.createVariable(currentFunction->getReturnPrecision(), - spv::StorageClassFunction, currentFunction->getReturnType()); - builder.setAccessChainLValue(copyId); - multiTypeStore(glslangReturnType, returnId); - returnId = builder.createLoad(copyId, currentFunction->getReturnPrecision()); - } - builder.makeReturn(false, returnId); - } else - builder.makeReturn(false); - - builder.clearAccessChain(); - break; - - case glslang::EOpDemote: - builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT); - builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation); - builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT); - break; - case glslang::EOpTerminateRayKHR: - builder.makeStatementTerminator(spv::OpTerminateRayKHR, "post-terminateRayKHR"); - break; - case glslang::EOpIgnoreIntersectionKHR: - builder.makeStatementTerminator(spv::OpIgnoreIntersectionKHR, "post-ignoreIntersectionKHR"); - break; - - default: - assert(0); - break; - } - - return false; -} - -spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node, spv::Id forcedType) -{ - // First, steer off constants, which are not SPIR-V variables, but - // can still have a mapping to a SPIR-V Id. - // This includes specialization constants. - if (node->getQualifier().isConstant()) { - spv::Id result = createSpvConstant(*node); - if (result != spv::NoResult) - return result; - } - - // Now, handle actual variables - spv::StorageClass storageClass = TranslateStorageClass(node->getType()); - spv::Id spvType = forcedType == spv::NoType ? convertGlslangToSpvType(node->getType()) - : forcedType; - - const bool contains16BitType = node->getType().contains16BitFloat() || - node->getType().contains16BitInt(); - if (contains16BitType) { - switch (storageClass) { - case spv::StorageClassInput: - case spv::StorageClassOutput: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - builder.addCapability(spv::CapabilityStorageInputOutput16); - break; - case spv::StorageClassUniform: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - if (node->getType().getQualifier().storage == glslang::EvqBuffer) - builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); - else - builder.addCapability(spv::CapabilityStorageUniform16); - break; - case spv::StorageClassPushConstant: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - builder.addCapability(spv::CapabilityStoragePushConstant16); - break; - case spv::StorageClassStorageBuffer: - case spv::StorageClassPhysicalStorageBufferEXT: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); - break; - default: - if (storageClass == spv::StorageClassWorkgroup && - node->getType().getBasicType() == glslang::EbtBlock) { - builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR); - break; - } - if (node->getType().contains16BitFloat()) - builder.addCapability(spv::CapabilityFloat16); - if (node->getType().contains16BitInt()) - builder.addCapability(spv::CapabilityInt16); - break; - } - } - - if (node->getType().contains8BitInt()) { - if (storageClass == spv::StorageClassPushConstant) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - builder.addCapability(spv::CapabilityStoragePushConstant8); - } else if (storageClass == spv::StorageClassUniform) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - builder.addCapability(spv::CapabilityUniformAndStorageBuffer8BitAccess); - } else if (storageClass == spv::StorageClassStorageBuffer) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - builder.addCapability(spv::CapabilityStorageBuffer8BitAccess); - } else if (storageClass == spv::StorageClassWorkgroup && - node->getType().getBasicType() == glslang::EbtBlock) { - builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR); - } else { - builder.addCapability(spv::CapabilityInt8); - } - } - - const char* name = node->getName().c_str(); - if (glslang::IsAnonymous(name)) - name = ""; - - spv::Id initializer = spv::NoResult; - - if (node->getType().getQualifier().storage == glslang::EvqUniform && !node->getConstArray().empty()) { - int nextConst = 0; - initializer = createSpvConstantFromConstUnionArray(node->getType(), - node->getConstArray(), - nextConst, - false /* specConst */); - } else if (node->getType().getQualifier().isNullInit()) { - initializer = builder.makeNullConstant(spvType); - } - - spv::Id var = builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false); - std::vector topLevelDecorations; - glslang::TQualifier typeQualifier = node->getType().getQualifier(); - TranslateMemoryDecoration(typeQualifier, topLevelDecorations, glslangIntermediate->usingVulkanMemoryModel()); - for (auto deco : topLevelDecorations) { - builder.addDecoration(var, deco); - } - return var; -} - -// Return type Id of the sampled type. -spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler) -{ - switch (sampler.type) { - case glslang::EbtInt: return builder.makeIntType(32); - case glslang::EbtUint: return builder.makeUintType(32); - case glslang::EbtFloat: return builder.makeFloatType(32); - case glslang::EbtFloat16: - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch); - builder.addCapability(spv::CapabilityFloat16ImageAMD); - return builder.makeFloatType(16); - case glslang::EbtInt64: - builder.addExtension(spv::E_SPV_EXT_shader_image_int64); - builder.addCapability(spv::CapabilityInt64ImageEXT); - return builder.makeIntType(64); - case glslang::EbtUint64: - builder.addExtension(spv::E_SPV_EXT_shader_image_int64); - builder.addCapability(spv::CapabilityInt64ImageEXT); - return builder.makeUintType(64); - default: - assert(0); - return builder.makeFloatType(32); - } -} - -// If node is a swizzle operation, return the type that should be used if -// the swizzle base is first consumed by another operation, before the swizzle -// is applied. -spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyped& node) -{ - if (node.getAsOperator() && - node.getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - return convertGlslangToSpvType(node.getAsBinaryNode()->getLeft()->getType()); - else - return spv::NoType; -} - -// When inverting a swizzle with a parent op, this function -// will apply the swizzle operation to a completed parent operation. -spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, - spv::Id parentResult) -{ - std::vector swizzle; - convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle); - return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle); -} - -// Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V. -void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector& swizzle) -{ - const glslang::TIntermSequence& swizzleSequence = node.getSequence(); - for (int i = 0; i < (int)swizzleSequence.size(); ++i) - swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst()); -} - -// Convert from a glslang type to an SPV type, by calling into a -// recursive version of this function. This establishes the inherited -// layout state rooted from the top-level type. -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly) -{ - return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false, forwardReferenceOnly); -} - -spv::LinkageType TGlslangToSpvTraverser::convertGlslangLinkageToSpv(glslang::TLinkType linkType) -{ - switch (linkType) { - case glslang::ELinkExport: - return spv::LinkageTypeExport; - default: - return spv::LinkageTypeMax; - } -} - -// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangStructToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, - glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier, - bool lastBufferBlockMember, bool forwardReferenceOnly) -{ - spv::Id spvType = spv::NoResult; - - switch (type.getBasicType()) { - case glslang::EbtVoid: - spvType = builder.makeVoidType(); - assert (! type.isArray()); - break; - case glslang::EbtBool: - // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is - // a 32-bit int where non-0 means true. - if (explicitLayout != glslang::ElpNone) - spvType = builder.makeUintType(32); - else - spvType = builder.makeBoolType(); - break; - case glslang::EbtInt: - spvType = builder.makeIntType(32); - break; - case glslang::EbtUint: - spvType = builder.makeUintType(32); - break; - case glslang::EbtFloat: - spvType = builder.makeFloatType(32); - break; - case glslang::EbtDouble: - spvType = builder.makeFloatType(64); - break; - case glslang::EbtFloat16: - spvType = builder.makeFloatType(16); - break; - case glslang::EbtInt8: - spvType = builder.makeIntType(8); - break; - case glslang::EbtUint8: - spvType = builder.makeUintType(8); - break; - case glslang::EbtInt16: - spvType = builder.makeIntType(16); - break; - case glslang::EbtUint16: - spvType = builder.makeUintType(16); - break; - case glslang::EbtInt64: - spvType = builder.makeIntType(64); - break; - case glslang::EbtUint64: - spvType = builder.makeUintType(64); - break; - case glslang::EbtAtomicUint: - builder.addCapability(spv::CapabilityAtomicStorage); - spvType = builder.makeUintType(32); - break; - case glslang::EbtAccStruct: - switch (glslangIntermediate->getStage()) { - case EShLangRayGen: - case EShLangIntersect: - case EShLangAnyHit: - case EShLangClosestHit: - case EShLangMiss: - case EShLangCallable: - // these all should have the RayTracingNV/KHR capability already - break; - default: - { - auto& extensions = glslangIntermediate->getRequestedExtensions(); - if (extensions.find("GL_EXT_ray_query") != extensions.end()) { - builder.addExtension(spv::E_SPV_KHR_ray_query); - builder.addCapability(spv::CapabilityRayQueryKHR); - } - } - break; - } - spvType = builder.makeAccelerationStructureType(); - break; - case glslang::EbtRayQuery: - { - auto& extensions = glslangIntermediate->getRequestedExtensions(); - if (extensions.find("GL_EXT_ray_query") != extensions.end()) { - builder.addExtension(spv::E_SPV_KHR_ray_query); - builder.addCapability(spv::CapabilityRayQueryKHR); - } - spvType = builder.makeRayQueryType(); - } - break; - case glslang::EbtReference: - { - // Make the forward pointer, then recurse to convert the structure type, then - // patch up the forward pointer with a real pointer type. - if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) { - spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT); - forwardPointers[type.getReferentType()] = forwardId; - } - spvType = forwardPointers[type.getReferentType()]; - if (!forwardReferenceOnly) { - spv::Id referentType = convertGlslangToSpvType(*type.getReferentType()); - builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT, - forwardPointers[type.getReferentType()], - referentType); - } - } - break; - case glslang::EbtSampler: - { - const glslang::TSampler& sampler = type.getSampler(); - if (sampler.isPureSampler()) { - spvType = builder.makeSamplerType(); - } else { - // an image is present, make its type - spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), - sampler.isShadow(), sampler.isArrayed(), sampler.isMultiSample(), - sampler.isImageClass() ? 2 : 1, TranslateImageFormat(type)); - if (sampler.isCombined() && - (!sampler.isBuffer() || glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6)) { - // Already has both image and sampler, make the combined type. Only combine sampler to - // buffer if before SPIR-V 1.6. - spvType = builder.makeSampledImageType(spvType); - } - } - } - break; - case glslang::EbtStruct: - case glslang::EbtBlock: - { - // If we've seen this struct type, return it - const glslang::TTypeList* glslangMembers = type.getStruct(); - - // Try to share structs for different layouts, but not yet for other - // kinds of qualification (primarily not yet including interpolant qualification). - if (! HasNonLayoutQualifiers(type, qualifier)) - spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers]; - if (spvType != spv::NoResult) - break; - - // else, we haven't seen it... - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size()); - spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); - } - break; - case glslang::EbtString: - // no type used for OpString - return 0; - - case glslang::EbtHitObjectNV: { - builder.addExtension(spv::E_SPV_NV_shader_invocation_reorder); - builder.addCapability(spv::CapabilityShaderInvocationReorderNV); - spvType = builder.makeHitObjectNVType(); - } - break; - case glslang::EbtSpirvType: { - // GL_EXT_spirv_intrinsics - const auto& spirvType = type.getSpirvType(); - const auto& spirvInst = spirvType.spirvInst; - - std::vector operands; - for (const auto& typeParam : spirvType.typeParams) { - if (typeParam.getAsConstant() != nullptr) { - // Constant expression - auto constant = typeParam.getAsConstant(); - if (constant->isLiteral()) { - if (constant->getBasicType() == glslang::EbtFloat) { - float floatValue = static_cast(constant->getConstArray()[0].getDConst()); - unsigned literal; - static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)"); - memcpy(&literal, &floatValue, sizeof(literal)); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtInt) { - unsigned literal = constant->getConstArray()[0].getIConst(); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtUint) { - unsigned literal = constant->getConstArray()[0].getUConst(); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtBool) { - unsigned literal = constant->getConstArray()[0].getBConst(); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtString) { - auto str = constant->getConstArray()[0].getSConst()->c_str(); - unsigned literal = 0; - char* literalPtr = reinterpret_cast(&literal); - unsigned charCount = 0; - char ch = 0; - do { - ch = *(str++); - *(literalPtr++) = ch; - ++charCount; - if (charCount == 4) { - operands.push_back({false, literal}); - literalPtr = reinterpret_cast(&literal); - charCount = 0; - } - } while (ch != 0); - - // Partial literal is padded with 0 - if (charCount > 0) { - for (; charCount < 4; ++charCount) - *(literalPtr++) = 0; - operands.push_back({false, literal}); - } - } else - assert(0); // Unexpected type - } else - operands.push_back({true, createSpvConstant(*constant)}); - } else { - // Type specifier - assert(typeParam.getAsType() != nullptr); - operands.push_back({true, convertGlslangToSpvType(*typeParam.getAsType())}); - } - } - - assert(spirvInst.set == ""); // Currently, couldn't be extended instructions. - spvType = builder.makeGenericType(static_cast(spirvInst.id), operands); - - break; - } - case glslang::EbtTensorLayoutNV: - { - builder.addCapability(spv::CapabilityTensorAddressingNV); - builder.addExtension(spv::E_SPV_NV_tensor_addressing); - - std::vector operands; - for (uint32_t i = 0; i < 2; ++i) { - operands.push_back({true, makeArraySizeId(*type.getTypeParameters()->arraySizes, i, true)}); - } - spvType = builder.makeGenericType(spv::OpTypeTensorLayoutNV, operands); - break; - } - case glslang::EbtTensorViewNV: - { - builder.addCapability(spv::CapabilityTensorAddressingNV); - builder.addExtension(spv::E_SPV_NV_tensor_addressing); - - uint32_t dim = type.getTypeParameters()->arraySizes->getDimSize(0); - assert(dim >= 1 && dim <= 5); - std::vector operands; - for (uint32_t i = 0; i < dim + 2; ++i) { - operands.push_back({true, makeArraySizeId(*type.getTypeParameters()->arraySizes, i, true, i==1)}); - } - spvType = builder.makeGenericType(spv::OpTypeTensorViewNV, operands); - break; - } - default: - assert(0); - break; - } - - if (type.isMatrix()) - spvType = builder.makeMatrixType(spvType, type.getMatrixCols(), type.getMatrixRows()); - else { - // If this variable has a vector element count greater than 1, create a SPIR-V vector - if (type.getVectorSize() > 1) - spvType = builder.makeVectorType(spvType, type.getVectorSize()); - } - - if (type.isCoopMatNV()) { - builder.addCapability(spv::CapabilityCooperativeMatrixNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix); - - if (type.getBasicType() == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityFloat16); - if (type.getBasicType() == glslang::EbtUint8 || - type.getBasicType() == glslang::EbtInt8) { - builder.addCapability(spv::CapabilityInt8); - } - - spv::Id scope = makeArraySizeId(*type.getTypeParameters()->arraySizes, 1); - spv::Id rows = makeArraySizeId(*type.getTypeParameters()->arraySizes, 2); - spv::Id cols = makeArraySizeId(*type.getTypeParameters()->arraySizes, 3); - - spvType = builder.makeCooperativeMatrixTypeNV(spvType, scope, rows, cols); - } - - if (type.isCoopMatKHR()) { - builder.addCapability(spv::CapabilityCooperativeMatrixKHR); - builder.addExtension(spv::E_SPV_KHR_cooperative_matrix); - - if (type.getBasicType() == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityFloat16); - if (type.getBasicType() == glslang::EbtUint8 || type.getBasicType() == glslang::EbtInt8) { - builder.addCapability(spv::CapabilityInt8); - } - - spv::Id scope = makeArraySizeId(*type.getTypeParameters()->arraySizes, 0); - spv::Id rows = makeArraySizeId(*type.getTypeParameters()->arraySizes, 1); - spv::Id cols = makeArraySizeId(*type.getTypeParameters()->arraySizes, 2); - spv::Id use = builder.makeUintConstant(type.getCoopMatKHRuse()); - - spvType = builder.makeCooperativeMatrixTypeKHR(spvType, scope, rows, cols, use); - } - - if (type.isArray()) { - int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride - - // Do all but the outer dimension - if (type.getArraySizes()->getNumDims() > 1) { - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) { - // Use a dummy glslang type for querying internal strides of - // arrays of arrays, but using just a one-dimensional array. - glslang::TType simpleArrayType(type, 0); // deference type of the array - while (simpleArrayType.getArraySizes()->getNumDims() > 1) - simpleArrayType.getArraySizes()->dereference(); - - // Will compute the higher-order strides here, rather than making a whole - // pile of types and doing repetitive recursion on their contents. - stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix); - } - - // make the arrays - for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) { - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), dim), stride); - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - stride *= type.getArraySizes()->getDimSize(dim); - } - } else { - // single-dimensional array, and don't yet have stride - - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) - stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix); - } - - // Do the outer dimension, which might not be known for a runtime-sized array. - // (Unsized arrays that survive through linking will be runtime-sized arrays) - if (type.isSizedArray()) - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride); - else { - if (!lastBufferBlockMember) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityRuntimeDescriptorArrayEXT); - } - spvType = builder.makeRuntimeArray(spvType); - } - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - } - - return spvType; -} - -// Apply SPIR-V decorations to the SPIR-V object (provided by SPIR-V ID). If member index is provided, the -// decorations are applied to this member. -void TGlslangToSpvTraverser::applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional member) -{ - assert(type.getQualifier().hasSpirvDecorate()); - - const glslang::TSpirvDecorate& spirvDecorate = type.getQualifier().getSpirvDecorate(); - - // Add spirv_decorate - for (auto& decorate : spirvDecorate.decorates) { - if (!decorate.second.empty()) { - std::vector literals; - TranslateLiterals(decorate.second, literals); - if (member.has_value()) - builder.addMemberDecoration(id, *member, static_cast(decorate.first), literals); - else - builder.addDecoration(id, static_cast(decorate.first), literals); - } else { - if (member.has_value()) - builder.addMemberDecoration(id, *member, static_cast(decorate.first)); - else - builder.addDecoration(id, static_cast(decorate.first)); - } - } - - // Add spirv_decorate_id - if (member.has_value()) { - // spirv_decorate_id not applied to members - assert(spirvDecorate.decorateIds.empty()); - } else { - for (auto& decorateId : spirvDecorate.decorateIds) { - std::vector operandIds; - assert(!decorateId.second.empty()); - for (auto extraOperand : decorateId.second) { - if (extraOperand->getQualifier().isFrontEndConstant()) - operandIds.push_back(createSpvConstant(*extraOperand)); - else - operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode())); - } - builder.addDecorationId(id, static_cast(decorateId.first), operandIds); - } - } - - // Add spirv_decorate_string - for (auto& decorateString : spirvDecorate.decorateStrings) { - std::vector strings; - assert(!decorateString.second.empty()); - for (auto extraOperand : decorateString.second) { - const char* string = extraOperand->getConstArray()[0].getSConst()->c_str(); - strings.push_back(string); - } - if (member.has_value()) - builder.addMemberDecoration(id, *member, static_cast(decorateString.first), strings); - else - builder.addDecoration(id, static_cast(decorateString.first), strings); - } -} - -// TODO: this functionality should exist at a higher level, in creating the AST -// -// Identify interface members that don't have their required extension turned on. -// -bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member) -{ - auto& extensions = glslangIntermediate->getRequestedExtensions(); - - if (member.getFieldName() == "gl_SecondaryViewportMaskNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - if (member.getFieldName() == "gl_SecondaryPositionNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - - if (glslangIntermediate->getStage() == EShLangMesh) { - if (member.getFieldName() == "gl_PrimitiveShadingRateEXT" && - extensions.find("GL_EXT_fragment_shading_rate") == extensions.end()) - return true; - } - - if (glslangIntermediate->getStage() != EShLangMesh) { - if (member.getFieldName() == "gl_ViewportMask" && - extensions.find("GL_NV_viewport_array2") == extensions.end()) - return true; - if (member.getFieldName() == "gl_PositionPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - if (member.getFieldName() == "gl_ViewportMaskPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - } - - return false; -} - -// Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier) -{ - // Create a vector of struct types for SPIR-V to consume - std::vector spvMembers; - int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, - // except sometimes for blocks - std::vector > deferredForwardPointers; - for (int i = 0; i < (int)glslangMembers->size(); i++) { - auto& glslangMember = (*glslangMembers)[i]; - if (glslangMember.type->hiddenMember()) { - ++memberDelta; - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; - } else { - if (type.getBasicType() == glslang::EbtBlock) { - if (filterMember(*glslangMember.type)) { - memberDelta++; - memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; - continue; - } - memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta; - } - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.type->getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // manually inherit location - if (! memberQualifier.hasLocation() && qualifier.hasLocation()) - memberQualifier.layoutLocation = qualifier.layoutLocation; - - // recurse - bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer && - i == (int)glslangMembers->size() - 1; - - // Make forward pointers for any pointer members. - if (glslangMember.type->isReference() && - forwardPointers.find(glslangMember.type->getReferentType()) == forwardPointers.end()) { - deferredForwardPointers.push_back(std::make_pair(glslangMember.type, memberQualifier)); - } - - // Create the member type. - auto const spvMember = convertGlslangToSpvType(*glslangMember.type, explicitLayout, memberQualifier, lastBufferBlockMember, - glslangMember.type->isReference()); - spvMembers.push_back(spvMember); - - // Update the builder with the type's location so that we can create debug types for the structure members. - // There doesn't exist a "clean" entry point for this information to be passed along to the builder so, for now, - // it is stored in the builder and consumed during the construction of composite debug types. - // TODO: This probably warrants further investigation. This approach was decided to be the least ugly of the - // quick and dirty approaches that were tried. - // Advantages of this approach: - // + Relatively clean. No direct calls into debug type system. - // + Handles nested recursive structures. - // Disadvantages of this approach: - // + Not as clean as desired. Traverser queries/sets persistent state. This is fragile. - // + Table lookup during creation of composite debug types. This really shouldn't be necessary. - if(options.emitNonSemanticShaderDebugInfo) { - builder.debugTypeLocs[spvMember].name = glslangMember.type->getFieldName().c_str(); - builder.debugTypeLocs[spvMember].line = glslangMember.loc.line; - builder.debugTypeLocs[spvMember].column = glslangMember.loc.column; - } - } - } - - // Make the SPIR-V type - spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str(), false); - if (! HasNonLayoutQualifiers(type, qualifier)) - structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType; - - // Decorate it - decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType, spvMembers); - - for (int i = 0; i < (int)deferredForwardPointers.size(); ++i) { - auto it = deferredForwardPointers[i]; - convertGlslangToSpvType(*it.first, explicitLayout, it.second, false); - } - - return spvType; -} - -void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier, - spv::Id spvType, - const std::vector& spvMembers) -{ - // Name and decorate the non-hidden members - int offset = -1; - bool memberLocationInvalid = type.isArrayOfArrays() || - (type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false)); - for (int i = 0; i < (int)glslangMembers->size(); i++) { - glslang::TType& glslangMember = *(*glslangMembers)[i].type; - int member = i; - if (type.getBasicType() == glslang::EbtBlock) { - member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i]; - if (filterMember(glslangMember)) - continue; - } - - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // using -1 above to indicate a hidden member - if (member < 0) - continue; - - builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str()); - builder.addMemberDecoration(spvType, member, - TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix)); - builder.addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember)); - // Add interpolation and auxiliary storage decorations only to - // top-level members of Input and Output storage classes - if (type.getQualifier().storage == glslang::EvqVaryingIn || - type.getQualifier().storage == glslang::EvqVaryingOut) { - if (type.getBasicType() == glslang::EbtBlock || - glslangIntermediate->getSource() == glslang::EShSourceHlsl) { - builder.addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier)); - builder.addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier)); - addMeshNVDecoration(spvType, member, memberQualifier); - } - } - builder.addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier)); - - if (type.getBasicType() == glslang::EbtBlock && - qualifier.storage == glslang::EvqBuffer) { - // Add memory decorations only to top-level members of shader storage block - std::vector memory; - TranslateMemoryDecoration(memberQualifier, memory, glslangIntermediate->usingVulkanMemoryModel()); - for (unsigned int i = 0; i < memory.size(); ++i) - builder.addMemberDecoration(spvType, member, memory[i]); - } - - // Location assignment was already completed correctly by the front end, - // just track whether a member needs to be decorated. - // Ignore member locations if the container is an array, as that's - // ill-specified and decisions have been made to not allow this. - if (!memberLocationInvalid && memberQualifier.hasLocation()) - builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation); - - // component, XFB, others - if (glslangMember.getQualifier().hasComponent()) - builder.addMemberDecoration(spvType, member, spv::DecorationComponent, - glslangMember.getQualifier().layoutComponent); - if (glslangMember.getQualifier().hasXfbOffset()) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, - glslangMember.getQualifier().layoutXfbOffset); - else if (explicitLayout != glslang::ElpNone) { - // figure out what to do with offset, which is accumulating - int nextOffset; - updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix); - if (offset >= 0) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); - offset = nextOffset; - } - - if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone) - builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, - getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix)); - - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true); - if (builtIn != spv::BuiltInMax) - builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); - - // nonuniform - builder.addMemberDecoration(spvType, member, TranslateNonUniformDecoration(glslangMember.getQualifier())); - - if (glslangIntermediate->getHlslFunctionality1() && memberQualifier.semanticName != nullptr) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, - memberQualifier.semanticName); - } - - if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (glslangMember.getQualifier().layoutViewportRelative){ - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){ - builder.addMemberDecoration(spvType, member, - (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, - glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - if (glslangMember.getQualifier().layoutPassthrough) { - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } - - // Add SPIR-V decorations (GL_EXT_spirv_intrinsics) - if (glslangMember.getQualifier().hasSpirvDecorate()) - applySpirvDecorate(glslangMember, spvType, member); - } - - // Decorate the structure - builder.addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); - const auto basicType = type.getBasicType(); - const auto typeStorageQualifier = type.getQualifier().storage; - if (basicType == glslang::EbtBlock) { - builder.addDecoration(spvType, TranslateBlockDecoration(typeStorageQualifier, glslangIntermediate->usingStorageBuffer())); - } else if (basicType == glslang::EbtStruct && glslangIntermediate->getSpv().vulkan > 0) { - const auto hasRuntimeArray = !spvMembers.empty() && builder.getOpCode(spvMembers.back()) == spv::OpTypeRuntimeArray; - if (hasRuntimeArray) { - builder.addDecoration(spvType, TranslateBlockDecoration(typeStorageQualifier, glslangIntermediate->usingStorageBuffer())); - } - } - - if (qualifier.hasHitObjectShaderRecordNV()) - builder.addDecoration(spvType, spv::DecorationHitObjectShaderRecordBufferNV); -} - -// Turn the expression forming the array size into an id. -// This is not quite trivial, because of specialization constants. -// Sometimes, a raw constant is turned into an Id, and sometimes -// a specialization constant expression is. -spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arraySizes, int dim, bool allowZero, bool boolType) -{ - // First, see if this is sized with a node, meaning a specialization constant: - glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim); - if (specNode != nullptr) { - builder.clearAccessChain(); - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - specNode->traverse(this); - return accessChainLoad(specNode->getAsTyped()->getType()); - } - - // Otherwise, need a compile-time (front end) size, get it: - int size = arraySizes.getDimSize(dim); - - if (!allowZero) - assert(size > 0); - - if (boolType) { - return builder.makeBoolConstant(size); - } else { - return builder.makeUintConstant(size); - } -} - -// Wrap the builder's accessChainLoad to: -// - localize handling of RelaxedPrecision -// - use the SPIR-V inferred type instead of another conversion of the glslang type -// (avoids unnecessary work and possible type punning for structures) -// - do conversion of concrete to abstract type -spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) -{ - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - - spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; - coherentFlags |= TranslateCoherent(type); - - spv::MemoryAccessMask accessMask = spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask); - // If the value being loaded is HelperInvocation, SPIR-V 1.6 is being generated (so that - // SPV_EXT_demote_to_helper_invocation is in core) and the memory model is in use, add - // the Volatile MemoryAccess semantic. - if (type.getQualifier().builtIn == glslang::EbvHelperInvocation && - glslangIntermediate->usingVulkanMemoryModel() && - glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - accessMask = spv::MemoryAccessMask(accessMask | spv::MemoryAccessVolatileMask); - } - - unsigned int alignment = builder.getAccessChain().alignment; - alignment |= type.getBufferReferenceAlignment(); - - spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), - TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags), - TranslateNonUniformDecoration(type.getQualifier()), - nominalTypeId, - accessMask, - TranslateMemoryScope(coherentFlags), - alignment); - - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - loadedId = convertLoadedBoolInUniformToUint(type, nominalTypeId, loadedId); - } - - return loadedId; -} - -// Wrap the builder's accessChainStore to: -// - do conversion of concrete to abstract type -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::Id rvalue) -{ - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = builder.makeUintConstant(1); - spv::Id zero = builder.makeUintConstant(0); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != boolType) - rvalue = builder.createBinOp(spv::OpINotEqual, boolType, rvalue, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = makeSmearedConstant(builder.makeUintConstant(1), vecSize); - spv::Id zero = makeSmearedConstant(builder.makeUintConstant(0), vecSize); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != bvecType) - rvalue = builder.createBinOp(spv::OpINotEqual, bvecType, rvalue, - makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } - } - - spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; - coherentFlags |= TranslateCoherent(type); - - unsigned int alignment = builder.getAccessChain().alignment; - alignment |= type.getBufferReferenceAlignment(); - - builder.accessChainStore(rvalue, TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags), - spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & - ~spv::MemoryAccessMakePointerVisibleKHRMask), - TranslateMemoryScope(coherentFlags), alignment); -} - -// For storing when types match at the glslang level, but not might match at the -// SPIR-V level. -// -// This especially happens when a single glslang type expands to multiple -// SPIR-V types, like a struct that is used in a member-undecorated way as well -// as in a member-decorated way. -// -// NOTE: This function can handle any store request; if it's not special it -// simplifies to a simple OpStore. -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id rValue) -{ - // we only do the complex path here if it's an aggregate - if (! type.isStruct() && ! type.isArray()) { - accessChainStore(type, rValue); - return; - } - - // and, it has to be a case of type aliasing - spv::Id rType = builder.getTypeId(rValue); - spv::Id lValue = builder.accessChainGetLValue(); - spv::Id lType = builder.getContainedTypeId(builder.getTypeId(lValue)); - if (lType == rType) { - accessChainStore(type, rValue); - return; - } - - // Recursively (as needed) copy an aggregate type to a different aggregate type, - // where the two types were the same type in GLSL. This requires member - // by member copy, recursively. - - // SPIR-V 1.4 added an instruction to do help do this. - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { - // However, bool in uniform space is changed to int, so - // OpCopyLogical does not work for that. - // TODO: It would be more robust to do a full recursive verification of the types satisfying SPIR-V rules. - bool rBool = builder.containsType(builder.getTypeId(rValue), spv::OpTypeBool, 0); - bool lBool = builder.containsType(lType, spv::OpTypeBool, 0); - if (lBool == rBool) { - spv::Id logicalCopy = builder.createUnaryOp(spv::OpCopyLogical, lType, rValue); - accessChainStore(type, logicalCopy); - return; - } - } - - // If an array, copy element by element. - if (type.isArray()) { - glslang::TType glslangElementType(type, 0); - spv::Id elementRType = builder.getContainedTypeId(rType); - for (int index = 0; index < type.getOuterArraySize(); ++index) { - // get the source member - spv::Id elementRValue = builder.createCompositeExtract(rValue, elementRType, index); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), - type.getBufferReferenceAlignment()); - - // store the member - multiTypeStore(glslangElementType, elementRValue); - } - } else { - assert(type.isStruct()); - - // loop over structure members - const glslang::TTypeList& members = *type.getStruct(); - for (int m = 0; m < (int)members.size(); ++m) { - const glslang::TType& glslangMemberType = *members[m].type; - - // get the source member - spv::Id memberRType = builder.getContainedTypeId(rType, m); - spv::Id memberRValue = builder.createCompositeExtract(rValue, memberRType, m); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), - type.getBufferReferenceAlignment()); - - // store the member - multiTypeStore(glslangMemberType, memberRValue); - } - } -} - -// Decide whether or not this type should be -// decorated with offsets and strides, and if so -// whether std140 or std430 rules should be applied. -glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang::TType& type) const -{ - // has to be a block - if (type.getBasicType() != glslang::EbtBlock) - return glslang::ElpNone; - - // has to be a uniform or buffer block or task in/out blocks - if (type.getQualifier().storage != glslang::EvqUniform && - type.getQualifier().storage != glslang::EvqBuffer && - type.getQualifier().storage != glslang::EvqShared && - !type.getQualifier().isTaskMemory()) - return glslang::ElpNone; - - // return the layout to use - switch (type.getQualifier().layoutPacking) { - case glslang::ElpStd140: - case glslang::ElpStd430: - case glslang::ElpScalar: - return type.getQualifier().layoutPacking; - default: - return glslang::ElpNone; - } -} - -// Given an array type, returns the integer stride required for that array -int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, - glslang::TLayoutMatrix matrixLayout) -{ - int size; - int stride; - glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, - matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix -// when used as a member of an interface block -int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, - glslang::TLayoutMatrix matrixLayout) -{ - glslang::TType elementType; - elementType.shallowCopy(matrixType); - elementType.clearArraySizes(); - - int size; - int stride; - glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, - matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a member type of a struct, realign the current offset for it, and compute -// the next (not yet aligned) offset for the next member, which will get aligned -// on the next call. -// 'currentOffset' should be passed in already initialized, ready to modify, and reflecting -// the migration of data from nextOffset -> currentOffset. It should be -1 on the first call. -// -1 means a non-forced member offset (no decoration needed). -void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, - int& currentOffset, int& nextOffset, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - // this will get a positive value when deemed necessary - nextOffset = -1; - - // override anything in currentOffset with user-set offset - if (memberType.getQualifier().hasOffset()) - currentOffset = memberType.getQualifier().layoutOffset; - - // It could be that current linker usage in glslang updated all the layoutOffset, - // in which case the following code does not matter. But, that's not quite right - // once cross-compilation unit GLSL validation is done, as the original user - // settings are needed in layoutOffset, and then the following will come into play. - - if (explicitLayout == glslang::ElpNone) { - if (! memberType.getQualifier().hasOffset()) - currentOffset = -1; - - return; - } - - // Getting this far means we need explicit offsets - if (currentOffset < 0) - currentOffset = 0; - - // Now, currentOffset is valid (either 0, or from a previous nextOffset), - // but possibly not yet correctly aligned. - - int memberSize; - int dummyStride; - int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, - matrixLayout == glslang::ElmRowMajor); - - bool isVectorLike = memberType.isVector(); - if (memberType.isMatrix()) { - if (matrixLayout == glslang::ElmRowMajor) - isVectorLike = memberType.getMatrixRows() == 1; - else - isVectorLike = memberType.getMatrixCols() == 1; - } - - // Adjust alignment for HLSL rules - // TODO: make this consistent in early phases of code: - // adjusting this late means inconsistencies with earlier code, which for reflection is an issue - // Until reflection is brought in sync with these adjustments, don't apply to $Global, - // which is the most likely to rely on reflection, and least likely to rely implicit layouts - if (glslangIntermediate->usingHlslOffsets() && - ! memberType.isStruct() && structType.getTypeName().compare("$Global") != 0) { - int componentSize; - int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, componentSize); - if (! memberType.isArray() && isVectorLike && componentAlignment <= 4) - memberAlignment = componentAlignment; - - // Don't add unnecessary padding after this member - // (undo std140 bumping size to a mutliple of vec4) - if (explicitLayout == glslang::ElpStd140) { - if (memberType.isMatrix()) { - if (matrixLayout == glslang::ElmRowMajor) - memberSize -= componentSize * (4 - memberType.getMatrixCols()); - else - memberSize -= componentSize * (4 - memberType.getMatrixRows()); - } else if (memberType.isArray()) - memberSize -= componentSize * (4 - memberType.getVectorSize()); - } - } - - // Bump up to member alignment - glslang::RoundToPow2(currentOffset, memberAlignment); - - // Bump up to vec4 if there is a bad straddle - if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, - currentOffset, isVectorLike)) - glslang::RoundToPow2(currentOffset, 16); - - nextOffset = currentOffset + memberSize; -} - -void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember) -{ - const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn; - switch (glslangBuiltIn) - { - case glslang::EbvPointSize: - case glslang::EbvClipDistance: - case glslang::EbvCullDistance: - case glslang::EbvViewportMaskNV: - case glslang::EbvSecondaryPositionNV: - case glslang::EbvSecondaryViewportMaskNV: - case glslang::EbvPositionPerViewNV: - case glslang::EbvViewportMaskPerViewNV: - case glslang::EbvTaskCountNV: - case glslang::EbvPrimitiveCountNV: - case glslang::EbvPrimitiveIndicesNV: - case glslang::EbvClipDistancePerViewNV: - case glslang::EbvCullDistancePerViewNV: - case glslang::EbvLayerPerViewNV: - case glslang::EbvMeshViewCountNV: - case glslang::EbvMeshViewIndicesNV: - // Generate the associated capability. Delegate to TranslateBuiltInDecoration. - // Alternately, we could just call this for any glslang built-in, since the - // capability already guards against duplicates. - TranslateBuiltInDecoration(glslangBuiltIn, false); - break; - default: - // Capabilities were already generated when the struct was declared. - break; - } -} - -bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate* node) -{ - return node->getName().compare(glslangIntermediate->getEntryPointMangledName().c_str()) == 0; -} - -// Does parameter need a place to keep writes, separate from the original? -// Assumes called after originalParam(), which filters out block/buffer/opaque-based -// qualifiers such that we should have only in/out/inout/constreadonly here. -bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier) const -{ - assert(qualifier == glslang::EvqIn || - qualifier == glslang::EvqOut || - qualifier == glslang::EvqInOut || - qualifier == glslang::EvqUniform || - qualifier == glslang::EvqConstReadOnly); - return qualifier != glslang::EvqConstReadOnly && - qualifier != glslang::EvqUniform; -} - -// Is parameter pass-by-original? -bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, const glslang::TType& paramType, - bool implicitThisParam) -{ - if (implicitThisParam) // implicit this - return true; - if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return paramType.getBasicType() == glslang::EbtBlock; - return (paramType.containsOpaque() && !glslangIntermediate->getBindlessMode()) || // sampler, etc. - paramType.getQualifier().isSpirvByReference() || // spirv_by_reference - (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO -} - -// Make all the functions, skeletally, without actually visiting their bodies. -void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) -{ - const auto getParamDecorations = [&](std::vector& decorations, const glslang::TType& type, - bool useVulkanMemoryModel) { - spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); - if (paramPrecision != spv::NoPrecision) - decorations.push_back(paramPrecision); - TranslateMemoryDecoration(type.getQualifier(), decorations, useVulkanMemoryModel); - if (type.isReference()) { - // Original and non-writable params pass the pointer directly and - // use restrict/aliased, others are stored to a pointer in Function - // memory and use RestrictPointer/AliasedPointer. - if (originalParam(type.getQualifier().storage, type, false) || - !writableParam(type.getQualifier().storage)) { - // TranslateMemoryDecoration added Restrict decoration already. - if (!type.getQualifier().isRestrict()) { - decorations.push_back(spv::DecorationAliased); - } - } else { - decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrictPointerEXT : - spv::DecorationAliasedPointerEXT); - } - } - }; - - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate(); - if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction) - continue; - - builder.setDebugSourceLocation(glslFunction->getLoc().line, glslFunction->getLoc().getFilename()); - - if (isShaderEntryPoint(glslFunction)) { - // For HLSL, the entry function is actually a compiler generated function to resolve the difference of - // entry function signature between HLSL and SPIR-V. So we don't emit debug information for that. - if (glslangIntermediate->getSource() != glslang::EShSourceHlsl) { - builder.setupFunctionDebugInfo(shaderEntry, glslangIntermediate->getEntryPointMangledName().c_str(), - std::vector(), // main function has no param - std::vector()); - } - continue; - } - // We're on a user function. Set up the basic interface for the function now, - // so that it's available to call. Translating the body will happen later. - // - // Typically (except for a "const in" parameter), an address will be passed to the - // function. What it is an address of varies: - // - // - "in" parameters not marked as "const" can be written to without modifying the calling - // argument so that write needs to be to a copy, hence the address of a copy works. - // - // - "const in" parameters can just be the r-value, as no writes need occur. - // - // - "out" and "inout" arguments can't be done as pointers to the calling argument, because - // GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy. - - std::vector paramTypes; - std::vector paramNames; - std::vector> paramDecorations; // list of decorations per parameter - glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence(); - -#ifdef ENABLE_HLSL - bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == - glslangIntermediate->implicitThisName; -#else - bool implicitThis = false; -#endif - - paramDecorations.resize(parameters.size()); - for (int p = 0; p < (int)parameters.size(); ++p) { - const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); - spv::Id typeId = convertGlslangToSpvType(paramType); - if (originalParam(paramType.getQualifier().storage, paramType, implicitThis && p == 0)) - typeId = builder.makePointer(TranslateStorageClass(paramType), typeId); - else if (writableParam(paramType.getQualifier().storage)) - typeId = builder.makePointer(spv::StorageClassFunction, typeId); - else - rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId()); - getParamDecorations(paramDecorations[p], paramType, glslangIntermediate->usingVulkanMemoryModel()); - paramTypes.push_back(typeId); - } - - for (auto const parameter:parameters) { - paramNames.push_back(parameter->getAsSymbolNode()->getName().c_str()); - } - - spv::Block* functionBlock; - spv::Function* function = builder.makeFunctionEntry( - TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()), - glslFunction->getName().c_str(), convertGlslangLinkageToSpv(glslFunction->getLinkType()), paramTypes, - paramDecorations, &functionBlock); - builder.setupFunctionDebugInfo(function, glslFunction->getName().c_str(), paramTypes, paramNames); - if (implicitThis) - function->setImplicitThis(); - - // Track function to emit/call later - functionMap[glslFunction->getName().c_str()] = function; - - // Set the parameter id's - for (int p = 0; p < (int)parameters.size(); ++p) { - symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p); - // give a name too - builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str()); - - const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); - if (paramType.contains8BitInt()) - builder.addCapability(spv::CapabilityInt8); - if (paramType.contains16BitInt()) - builder.addCapability(spv::CapabilityInt16); - if (paramType.contains16BitFloat()) - builder.addCapability(spv::CapabilityFloat16); - } - } -} - -// Process all the initializers, while skipping the functions and link objects -void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequence& initializers) -{ - builder.setBuildPoint(shaderEntry->getLastBlock()); - for (int i = 0; i < (int)initializers.size(); ++i) { - glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate(); - if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != - glslang::EOpLinkerObjects) { - - // We're on a top-level node that's not a function. Treat as an initializer, whose - // code goes into the beginning of the entry point. - initializer->traverse(this); - } - } -} -// Walk over all linker objects to create a map for payload and callable data linker objects -// and their location to be used during codegen for OpTraceKHR and OpExecuteCallableKHR -// This is done here since it is possible that these linker objects are not be referenced in the AST -void TGlslangToSpvTraverser::collectRayTracingLinkerObjects() -{ - glslang::TIntermAggregate* linkerObjects = glslangIntermediate->findLinkerObjects(); - for (auto& objSeq : linkerObjects->getSequence()) { - auto objNode = objSeq->getAsSymbolNode(); - if (objNode != nullptr) { - if (objNode->getQualifier().hasLocation()) { - unsigned int location = objNode->getQualifier().layoutLocation; - auto st = objNode->getQualifier().storage; - int set; - switch (st) - { - case glslang::EvqPayload: - case glslang::EvqPayloadIn: - set = 0; - break; - case glslang::EvqCallableData: - case glslang::EvqCallableDataIn: - set = 1; - break; - - case glslang::EvqHitObjectAttrNV: - set = 2; - break; - - default: - set = -1; - } - if (set != -1) - locationToSymbol[set].insert(std::make_pair(location, objNode)); - } - } - } -} -// Process all the functions, while skipping initializers. -void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions) -{ - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* node = glslFunctions[f]->getAsAggregate(); - if (node && (node->getOp() == glslang::EOpFunction || node->getOp() == glslang::EOpLinkerObjects)) - node->traverse(this); - } -} - -void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node) -{ - // SPIR-V functions should already be in the functionMap from the prepass - // that called makeFunctions(). - currentFunction = functionMap[node->getName().c_str()]; - spv::Block* functionBlock = currentFunction->getEntryBlock(); - builder.setBuildPoint(functionBlock); - builder.enterFunction(currentFunction); -} - -void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, - spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) -{ - const glslang::TIntermSequence& glslangArguments = node.getSequence(); - - glslang::TSampler sampler = {}; - bool cubeCompare = false; - bool f16ShadowCompare = false; - if (node.isTexture() || node.isImage()) { - sampler = glslangArguments[0]->getAsTyped()->getType().getSampler(); - cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; - f16ShadowCompare = sampler.shadow && - glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; - } - - for (int i = 0; i < (int)glslangArguments.size(); ++i) { - builder.clearAccessChain(); - glslangArguments[i]->traverse(this); - - // Special case l-value operands - bool lvalue = false; - switch (node.getOp()) { - case glslang::EOpImageAtomicAdd: - case glslang::EOpImageAtomicMin: - case glslang::EOpImageAtomicMax: - case glslang::EOpImageAtomicAnd: - case glslang::EOpImageAtomicOr: - case glslang::EOpImageAtomicXor: - case glslang::EOpImageAtomicExchange: - case glslang::EOpImageAtomicCompSwap: - case glslang::EOpImageAtomicLoad: - case glslang::EOpImageAtomicStore: - if (i == 0) - lvalue = true; - break; - case glslang::EOpSparseImageLoad: - if ((sampler.ms && i == 3) || (! sampler.ms && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTexture: - if (((cubeCompare || f16ShadowCompare) && i == 3) || (! (cubeCompare || f16ShadowCompare) && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureClamp: - if (((cubeCompare || f16ShadowCompare) && i == 4) || (! (cubeCompare || f16ShadowCompare) && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLod: - case glslang::EOpSparseTextureOffset: - if ((f16ShadowCompare && i == 4) || (! f16ShadowCompare && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureFetch: - if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureFetchOffset: - if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLodOffset: - case glslang::EOpSparseTextureGrad: - case glslang::EOpSparseTextureOffsetClamp: - if ((f16ShadowCompare && i == 5) || (! f16ShadowCompare && i == 4)) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffset: - case glslang::EOpSparseTextureGradClamp: - if ((f16ShadowCompare && i == 6) || (! f16ShadowCompare && i == 5)) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffsetClamp: - if ((f16ShadowCompare && i == 7) || (! f16ShadowCompare && i == 6)) - lvalue = true; - break; - case glslang::EOpSparseTextureGather: - if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherOffset: - case glslang::EOpSparseTextureGatherOffsets: - if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherLod: - if (i == 3) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherLodOffset: - case glslang::EOpSparseTextureGatherLodOffsets: - if (i == 4) - lvalue = true; - break; - case glslang::EOpSparseImageLoadLod: - if (i == 3) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintNV: - if (i == 4) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintClampNV: - case glslang::EOpImageSampleFootprintLodNV: - if (i == 5) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintGradNV: - if (i == 6) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintGradClampNV: - if (i == 7) - lvalue = true; - break; - case glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: - if (i == 2) - lvalue = true; - break; - default: - break; - } - - if (lvalue) { - spv::Id lvalue_id = builder.accessChainGetLValue(); - arguments.push_back(lvalue_id); - lvalueCoherentFlags = builder.getAccessChain().coherentFlags; - builder.addDecoration(lvalue_id, TranslateNonUniformDecoration(lvalueCoherentFlags)); - lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType()); - } else { - if (i > 0 && - glslangArguments[i]->getAsSymbolNode() && glslangArguments[i-1]->getAsSymbolNode() && - glslangArguments[i]->getAsSymbolNode()->getId() == glslangArguments[i-1]->getAsSymbolNode()->getId()) { - // Reuse the id if possible - arguments.push_back(arguments[i-1]); - } else { - arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType())); - } - } - } -} - -void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector& arguments) -{ - builder.clearAccessChain(); - node.getOperand()->traverse(this); - arguments.push_back(accessChainLoad(node.getOperand()->getType())); -} - -spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node) -{ - if (! node->isImage() && ! node->isTexture()) - return spv::NoResult; - - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - - // Process a GLSL texturing op (will be SPV image) - - const glslang::TType &imageType = node->getAsAggregate() - ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType() - : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType(); - const glslang::TSampler sampler = imageType.getSampler(); - bool f16ShadowCompare = (sampler.shadow && node->getAsAggregate()) - ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16 - : false; - - const auto signExtensionMask = [&]() { - if (builder.getSpvVersion() >= spv::Spv_1_4) { - if (sampler.type == glslang::EbtUint) - return spv::ImageOperandsZeroExtendMask; - else if (sampler.type == glslang::EbtInt) - return spv::ImageOperandsSignExtendMask; - } - return spv::ImageOperandsMaskNone; - }; - - spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; - - std::vector arguments; - if (node->getAsAggregate()) - translateArguments(*node->getAsAggregate(), arguments, lvalueCoherentFlags); - else - translateArguments(*node->getAsUnaryNode(), arguments); - spv::Decoration precision = TranslatePrecisionDecoration(node->getType()); - - spv::Builder::TextureParameters params = { }; - params.sampler = arguments[0]; - - glslang::TCrackedTextureOp cracked; - node->crackTexture(sampler, cracked); - - const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint; - - if (builder.isSampledImage(params.sampler) && - ((cracked.query && node->getOp() != glslang::EOpTextureQueryLod) || cracked.fragMask || cracked.fetch)) { - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - if (imageType.getQualifier().isNonUniform()) { - builder.addDecoration(params.sampler, spv::DecorationNonUniformEXT); - } - } - // Check for queries - if (cracked.query) { - switch (node->getOp()) { - case glslang::EOpImageQuerySize: - case glslang::EOpTextureQuerySize: - if (arguments.size() > 1) { - params.lod = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult); - } else - return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult); - case glslang::EOpImageQuerySamples: - case glslang::EOpTextureQuerySamples: - return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult); - case glslang::EOpTextureQueryLod: - params.coords = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQueryLod, params, isUnsignedResult); - case glslang::EOpTextureQueryLevels: - return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult); - case glslang::EOpSparseTexelsResident: - return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]); - default: - assert(0); - break; - } - } - - int components = node->getType().getVectorSize(); - - if (node->getOp() == glslang::EOpImageLoad || - node->getOp() == glslang::EOpImageLoadLod || - node->getOp() == glslang::EOpTextureFetch || - node->getOp() == glslang::EOpTextureFetchOffset) { - // These must produce 4 components, per SPIR-V spec. We'll add a conversion constructor if needed. - // This will only happen through the HLSL path for operator[], so we do not have to handle e.g. - // the EOpTexture/Proj/Lod/etc family. It would be harmless to do so, but would need more logic - // here around e.g. which ones return scalars or other types. - components = 4; - } - - glslang::TType returnType(node->getType().getBasicType(), glslang::EvqTemporary, components); - - auto resultType = [&returnType,this]{ return convertGlslangToSpvType(returnType); }; - - // Check for image functions other than queries - if (node->isImage()) { - std::vector operands; - auto opIt = arguments.begin(); - spv::IdImmediate image = { true, *(opIt++) }; - operands.push_back(image); - - // Handle subpass operations - // TODO: GLSL should change to have the "MS" only on the type rather than the - // built-in function. - if (cracked.subpass) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - spv::IdImmediate coord = { true, - builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps) }; - operands.push_back(coord); - spv::IdImmediate imageOperands = { false, spv::ImageOperandsMaskNone }; - imageOperands.word = imageOperands.word | signExtensionMask(); - if (sampler.isMultiSample()) { - imageOperands.word = imageOperands.word | spv::ImageOperandsSampleMask; - } - if (imageOperands.word != spv::ImageOperandsMaskNone) { - operands.push_back(imageOperands); - if (sampler.isMultiSample()) { - spv::IdImmediate imageOperand = { true, *(opIt++) }; - operands.push_back(imageOperand); - } - } - spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands); - builder.setPrecision(result, precision); - return result; - } - - if (cracked.attachmentEXT) { - if (opIt != arguments.end()) { - spv::IdImmediate sample = { true, *opIt }; - operands.push_back(sample); - } - spv::Id result = builder.createOp(spv::OpColorAttachmentReadEXT, resultType(), operands); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.setPrecision(result, precision); - return result; - } - - spv::IdImmediate coord = { true, *(opIt++) }; - operands.push_back(coord); - if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) { - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.isMultiSample()) { - mask = mask | spv::ImageOperandsSampleMask; - } - if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - mask = mask | spv::ImageOperandsLodMask; - } - mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); - mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask); - mask = mask | signExtensionMask(); - if (mask != spv::ImageOperandsMaskNone) { - spv::IdImmediate imageOperands = { false, (unsigned int)mask }; - operands.push_back(imageOperands); - } - if (mask & spv::ImageOperandsSampleMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsLodMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { - spv::IdImmediate imageOperand = { true, - builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; - operands.push_back(imageOperand); - } - - if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - std::vector result(1, builder.createOp(spv::OpImageRead, resultType(), operands)); - builder.setPrecision(result[0], precision); - - // If needed, add a conversion constructor to the proper size. - if (components != node->getType().getVectorSize()) - result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType())); - - return result[0]; - } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) { - - // Push the texel value before the operands - if (sampler.isMultiSample() || cracked.lod) { - spv::IdImmediate texel = { true, *(opIt + 1) }; - operands.push_back(texel); - } else { - spv::IdImmediate texel = { true, *opIt }; - operands.push_back(texel); - } - - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.isMultiSample()) { - mask = mask | spv::ImageOperandsSampleMask; - } - if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - mask = mask | spv::ImageOperandsLodMask; - } - mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); - mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelVisibleKHRMask); - mask = mask | signExtensionMask(); - if (mask != spv::ImageOperandsMaskNone) { - spv::IdImmediate imageOperands = { false, (unsigned int)mask }; - operands.push_back(imageOperands); - } - if (mask & spv::ImageOperandsSampleMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsLodMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsMakeTexelAvailableKHRMask) { - spv::IdImmediate imageOperand = { true, - builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; - operands.push_back(imageOperand); - } - - builder.createNoResultOp(spv::OpImageWrite, operands); - if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat); - return spv::NoResult; - } else if (node->getOp() == glslang::EOpSparseImageLoad || - node->getOp() == glslang::EOpSparseImageLoadLod) { - builder.addCapability(spv::CapabilitySparseResidency); - if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.isMultiSample()) { - mask = mask | spv::ImageOperandsSampleMask; - } - if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - mask = mask | spv::ImageOperandsLodMask; - } - mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); - mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask); - mask = mask | signExtensionMask(); - if (mask != spv::ImageOperandsMaskNone) { - spv::IdImmediate imageOperands = { false, (unsigned int)mask }; - operands.push_back(imageOperands); - } - if (mask & spv::ImageOperandsSampleMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsLodMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { - spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope( - TranslateCoherent(imageType))) }; - operands.push_back(imageOperand); - } - - // Create the return type that was a special structure - spv::Id texelOut = *opIt; - spv::Id typeId0 = resultType(); - spv::Id typeId1 = builder.getDerefTypeId(texelOut); - spv::Id resultTypeId = builder.makeStructResultType(typeId0, typeId1); - - spv::Id resultId = builder.createOp(spv::OpImageSparseRead, resultTypeId, operands); - - // Decode the return type - builder.createStore(builder.createCompositeExtract(resultId, typeId1, 1), texelOut); - return builder.createCompositeExtract(resultId, typeId0, 0); - } else { - // Process image atomic operations - - // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer, - // as the first source operand, is required by SPIR-V atomic operations. - // For non-MS, the sample value should be 0 - spv::IdImmediate sample = { true, sampler.isMultiSample() ? *(opIt++) : builder.makeUintConstant(0) }; - operands.push_back(sample); - - spv::Id resultTypeId; - glslang::TBasicType typeProxy = node->getBasicType(); - // imageAtomicStore has a void return type so base the pointer type on - // the type of the value operand. - if (node->getOp() == glslang::EOpImageAtomicStore) { - resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(*opIt)); - typeProxy = node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler().type; - } else { - resultTypeId = builder.makePointer(spv::StorageClassImage, resultType()); - } - spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands); - if (imageType.getQualifier().nonUniform) { - builder.addDecoration(pointer, spv::DecorationNonUniformEXT); - } - - std::vector operands; - operands.push_back(pointer); - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - return createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy, - lvalueCoherentFlags, node->getType()); - } - } - - // Check for fragment mask functions other than queries - if (cracked.fragMask) { - assert(sampler.ms); - - auto opIt = arguments.begin(); - std::vector operands; - - operands.push_back(params.sampler); - ++opIt; - - if (sampler.isSubpass()) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant( - builder.makeVectorType(builder.makeIntType(32), 2), comps)); - } - - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - spv::Op fragMaskOp = spv::OpNop; - if (node->getOp() == glslang::EOpFragmentMaskFetch) - fragMaskOp = spv::OpFragmentMaskFetchAMD; - else if (node->getOp() == glslang::EOpFragmentFetch) - fragMaskOp = spv::OpFragmentFetchAMD; - - builder.addExtension(spv::E_SPV_AMD_shader_fragment_mask); - builder.addCapability(spv::CapabilityFragmentMaskAMD); - return builder.createOp(fragMaskOp, resultType(), operands); - } - - // Check for texture functions other than queries - bool sparse = node->isSparseTexture(); - bool imageFootprint = node->isImageFootprint(); - bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.isArrayed() && sampler.isShadow(); - - // check for bias argument - bool bias = false; - if (! cracked.lod && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { - int nonBiasArgCount = 2; - if (cracked.gather) - ++nonBiasArgCount; // comp argument should be present when bias argument is present - - if (f16ShadowCompare) - ++nonBiasArgCount; - if (cracked.offset) - ++nonBiasArgCount; - else if (cracked.offsets) - ++nonBiasArgCount; - if (cracked.grad) - nonBiasArgCount += 2; - if (cracked.lodClamp) - ++nonBiasArgCount; - if (sparse) - ++nonBiasArgCount; - if (imageFootprint) - //Following three extra arguments - // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint - nonBiasArgCount += 3; - if ((int)arguments.size() > nonBiasArgCount) - bias = true; - } - - if (cracked.gather) { - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - if (bias || cracked.lod || - sourceExtensions.find(glslang::E_GL_AMD_texture_gather_bias_lod) != sourceExtensions.end()) { - builder.addExtension(spv::E_SPV_AMD_texture_gather_bias_lod); - builder.addCapability(spv::CapabilityImageGatherBiasLodAMD); - } - } - - // set the rest of the arguments - - params.coords = arguments[1]; - int extraArgs = 0; - bool noImplicitLod = false; - - // sort out where Dref is coming from - if (cubeCompare || f16ShadowCompare) { - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow && cracked.gather) { - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow) { - std::vector indexes; - int dRefComp; - if (cracked.proj) - dRefComp = 2; // "The resulting 3rd component of P in the shadow forms is used as Dref" - else - dRefComp = builder.getNumComponents(params.coords) - 1; - indexes.push_back(dRefComp); - params.Dref = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); - } - - // lod - if (cracked.lod) { - params.lod = arguments[2 + extraArgs]; - ++extraArgs; - } else if (glslangIntermediate->getStage() != EShLangFragment && - !(glslangIntermediate->getStage() == EShLangCompute && - glslangIntermediate->hasLayoutDerivativeModeNone())) { - // we need to invent the default lod for an explicit lod instruction for a non-fragment stage - noImplicitLod = true; - } - - // multisample - if (sampler.isMultiSample()) { - params.sample = arguments[2 + extraArgs]; // For MS, "sample" should be specified - ++extraArgs; - } - - // gradient - if (cracked.grad) { - params.gradX = arguments[2 + extraArgs]; - params.gradY = arguments[3 + extraArgs]; - extraArgs += 2; - } - - // offset and offsets - if (cracked.offset) { - params.offset = arguments[2 + extraArgs]; - ++extraArgs; - } else if (cracked.offsets) { - params.offsets = arguments[2 + extraArgs]; - ++extraArgs; - } - - // lod clamp - if (cracked.lodClamp) { - params.lodClamp = arguments[2 + extraArgs]; - ++extraArgs; - } - // sparse - if (sparse) { - params.texelOut = arguments[2 + extraArgs]; - ++extraArgs; - } - // gather component - if (cracked.gather && ! sampler.shadow) { - // default component is 0, if missing, otherwise an argument - if (2 + extraArgs < (int)arguments.size()) { - params.component = arguments[2 + extraArgs]; - ++extraArgs; - } else - params.component = builder.makeIntConstant(0); - } - spv::Id resultStruct = spv::NoResult; - if (imageFootprint) { - //Following three extra arguments - // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint - params.granularity = arguments[2 + extraArgs]; - params.coarse = arguments[3 + extraArgs]; - resultStruct = arguments[4 + extraArgs]; - extraArgs += 3; - } - - // bias - if (bias) { - params.bias = arguments[2 + extraArgs]; - ++extraArgs; - } - - if (imageFootprint) { - builder.addExtension(spv::E_SPV_NV_shader_image_footprint); - builder.addCapability(spv::CapabilityImageFootprintNV); - - - //resultStructType(OpenGL type) contains 5 elements: - //struct gl_TextureFootprint2DNV { - // uvec2 anchor; - // uvec2 offset; - // uvec2 mask; - // uint lod; - // uint granularity; - //}; - //or - //struct gl_TextureFootprint3DNV { - // uvec3 anchor; - // uvec3 offset; - // uvec2 mask; - // uint lod; - // uint granularity; - //}; - spv::Id resultStructType = builder.getContainedTypeId(builder.getTypeId(resultStruct)); - assert(builder.isStructType(resultStructType)); - - //resType (SPIR-V type) contains 6 elements: - //Member 0 must be a Boolean type scalar(LOD), - //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor), - //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset), - //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask), - //Member 4 must be a scalar of integer type, whose Signedness operand is 0(lod), - //Member 5 must be a scalar of integer type, whose Signedness operand is 0(granularity). - std::vector members; - members.push_back(resultType()); - for (int i = 0; i < 5; i++) { - members.push_back(builder.getContainedTypeId(resultStructType, i)); - } - spv::Id resType = builder.makeStructType(members, "ResType"); - - //call ImageFootprintNV - spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj, - cracked.gather, noImplicitLod, params, signExtensionMask()); - - //copy resType (SPIR-V type) to resultStructType(OpenGL type) - for (int i = 0; i < 5; i++) { - builder.clearAccessChain(); - builder.setAccessChainLValue(resultStruct); - - //Accessing to a struct we created, no coherent flag is set - spv::Builder::AccessChain::CoherentFlags flags; - flags.clear(); - - builder.accessChainPush(builder.makeIntConstant(i), flags, 0); - builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), - i+1), TranslateNonUniformDecoration(imageType.getQualifier())); - } - return builder.createCompositeExtract(res, resultType(), 0); - } - - // projective component (might not to move) - // GLSL: "The texture coordinates consumed from P, not including the last component of P, - // are divided by the last component of P." - // SPIR-V: "... (u [, v] [, w], q)... It may be a vector larger than needed, but all - // unused components will appear after all used components." - if (cracked.proj) { - int projSourceComp = builder.getNumComponents(params.coords) - 1; - int projTargetComp; - switch (sampler.dim) { - case glslang::Esd1D: projTargetComp = 1; break; - case glslang::Esd2D: projTargetComp = 2; break; - case glslang::EsdRect: projTargetComp = 2; break; - default: projTargetComp = projSourceComp; break; - } - // copy the projective coordinate if we have to - if (projTargetComp != projSourceComp) { - spv::Id projComp = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), projSourceComp); - params.coords = builder.createCompositeInsert(projComp, params.coords, - builder.getTypeId(params.coords), projTargetComp); - } - } - - // nonprivate - if (imageType.getQualifier().nonprivate) { - params.nonprivate = true; - } - - // volatile - if (imageType.getQualifier().volatil) { - params.volatil = true; - } - - std::vector result( 1, - builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, - noImplicitLod, params, signExtensionMask()) - ); - - if (components != node->getType().getVectorSize()) - result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType())); - - return result[0]; -} - -spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node) -{ - // Grab the function's pointer from the previously created function - spv::Function* function = functionMap[node->getName().c_str()]; - if (! function) - return 0; - - const glslang::TIntermSequence& glslangArgs = node->getSequence(); - const glslang::TQualifierList& qualifiers = node->getQualifierList(); - - // See comments in makeFunctions() for details about the semantics for parameter passing. - // - // These imply we need a four step process: - // 1. Evaluate the arguments - // 2. Allocate and make copies of in, out, and inout arguments - // 3. Make the call - // 4. Copy back the results - - // 1. Evaluate the arguments and their types - std::vector lValues; - std::vector rValues; - std::vector argTypes; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - argTypes.push_back(&glslangArgs[a]->getAsTyped()->getType()); - // build l-value - builder.clearAccessChain(); - glslangArgs[a]->traverse(this); - // keep outputs and pass-by-originals as l-values, evaluate others as r-values - if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0) || - writableParam(qualifiers[a])) { - // save l-value - lValues.push_back(builder.getAccessChain()); - } else { - // process r-value - rValues.push_back(accessChainLoad(*argTypes.back())); - } - } - - // Reset source location to the function call location after argument evaluation - builder.setDebugSourceLocation(node->getLoc().line, node->getLoc().getFilename()); - - // 2. Allocate space for anything needing a copy, and if it's "in" or "inout" - // copy the original into that space. - // - // Also, build up the list of actual arguments to pass in for the call - int lValueCount = 0; - int rValueCount = 0; - std::vector spvArgs; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - spv::Id arg; - if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0)) { - builder.setAccessChain(lValues[lValueCount]); - arg = builder.accessChainGetLValue(); - ++lValueCount; - } else if (writableParam(qualifiers[a])) { - // need space to hold the copy - arg = builder.createVariable(function->getParamPrecision(a), spv::StorageClassFunction, - builder.getContainedTypeId(function->getParamType(a)), "param"); - if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) { - // need to copy the input into output space - builder.setAccessChain(lValues[lValueCount]); - spv::Id copy = accessChainLoad(*argTypes[a]); - builder.clearAccessChain(); - builder.setAccessChainLValue(arg); - multiTypeStore(*argTypes[a], copy); - } - ++lValueCount; - } else { - // process r-value, which involves a copy for a type mismatch - if (function->getParamType(a) != builder.getTypeId(rValues[rValueCount]) || - TranslatePrecisionDecoration(*argTypes[a]) != function->getParamPrecision(a)) - { - spv::Id argCopy = builder.createVariable(function->getParamPrecision(a), spv::StorageClassFunction, function->getParamType(a), "arg"); - builder.clearAccessChain(); - builder.setAccessChainLValue(argCopy); - multiTypeStore(*argTypes[a], rValues[rValueCount]); - arg = builder.createLoad(argCopy, function->getParamPrecision(a)); - } else - arg = rValues[rValueCount]; - ++rValueCount; - } - spvArgs.push_back(arg); - } - - // 3. Make the call. - spv::Id result = builder.createFunctionCall(function, spvArgs); - builder.setPrecision(result, TranslatePrecisionDecoration(node->getType())); - builder.addDecoration(result, TranslateNonUniformDecoration(node->getType().getQualifier())); - - // 4. Copy back out an "out" arguments. - lValueCount = 0; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0)) - ++lValueCount; - else if (writableParam(qualifiers[a])) { - if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) { - spv::Id copy = builder.createLoad(spvArgs[a], spv::NoPrecision); - builder.addDecoration(copy, TranslateNonUniformDecoration(argTypes[a]->getQualifier())); - builder.setAccessChain(lValues[lValueCount]); - multiTypeStore(*argTypes[a], copy); - } - ++lValueCount; - } - } - - return result; -} - -// Translate AST operation to SPV operation, already having SPV-based operands/types. -spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpDecorations& decorations, - spv::Id typeId, spv::Id left, spv::Id right, - glslang::TBasicType typeProxy, bool reduceComparison) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - bool isBool = typeProxy == glslang::EbtBool; - - spv::Op binOp = spv::OpNop; - bool needMatchingVectors = true; // for non-matrix ops, would a scalar need to smear to match a vector? - bool comparison = false; - - switch (op) { - case glslang::EOpAdd: - case glslang::EOpAddAssign: - if (isFloat) - binOp = spv::OpFAdd; - else - binOp = spv::OpIAdd; - break; - case glslang::EOpSub: - case glslang::EOpSubAssign: - if (isFloat) - binOp = spv::OpFSub; - else - binOp = spv::OpISub; - break; - case glslang::EOpMul: - case glslang::EOpMulAssign: - if (isFloat) - binOp = spv::OpFMul; - else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesScalar: - case glslang::EOpVectorTimesScalarAssign: - if (isFloat && (builder.isVector(left) || builder.isVector(right))) { - if (builder.isVector(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - needMatchingVectors = false; - binOp = spv::OpVectorTimesScalar; - } else if (isFloat) - binOp = spv::OpFMul; - else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesMatrix: - case glslang::EOpVectorTimesMatrixAssign: - binOp = spv::OpVectorTimesMatrix; - break; - case glslang::EOpMatrixTimesVector: - binOp = spv::OpMatrixTimesVector; - break; - case glslang::EOpMatrixTimesScalar: - case glslang::EOpMatrixTimesScalarAssign: - binOp = spv::OpMatrixTimesScalar; - break; - case glslang::EOpMatrixTimesMatrix: - case glslang::EOpMatrixTimesMatrixAssign: - binOp = spv::OpMatrixTimesMatrix; - break; - case glslang::EOpOuterProduct: - binOp = spv::OpOuterProduct; - needMatchingVectors = false; - break; - - case glslang::EOpDiv: - case glslang::EOpDivAssign: - if (isFloat) - binOp = spv::OpFDiv; - else if (isUnsigned) - binOp = spv::OpUDiv; - else - binOp = spv::OpSDiv; - break; - case glslang::EOpMod: - case glslang::EOpModAssign: - if (isFloat) - binOp = spv::OpFMod; - else if (isUnsigned) - binOp = spv::OpUMod; - else - binOp = spv::OpSMod; - break; - case glslang::EOpRightShift: - case glslang::EOpRightShiftAssign: - if (isUnsigned) - binOp = spv::OpShiftRightLogical; - else - binOp = spv::OpShiftRightArithmetic; - break; - case glslang::EOpLeftShift: - case glslang::EOpLeftShiftAssign: - binOp = spv::OpShiftLeftLogical; - break; - case glslang::EOpAnd: - case glslang::EOpAndAssign: - binOp = spv::OpBitwiseAnd; - break; - case glslang::EOpLogicalAnd: - needMatchingVectors = false; - binOp = spv::OpLogicalAnd; - break; - case glslang::EOpInclusiveOr: - case glslang::EOpInclusiveOrAssign: - binOp = spv::OpBitwiseOr; - break; - case glslang::EOpLogicalOr: - needMatchingVectors = false; - binOp = spv::OpLogicalOr; - break; - case glslang::EOpExclusiveOr: - case glslang::EOpExclusiveOrAssign: - binOp = spv::OpBitwiseXor; - break; - case glslang::EOpLogicalXor: - needMatchingVectors = false; - binOp = spv::OpLogicalNotEqual; - break; - - case glslang::EOpAbsDifference: - binOp = isUnsigned ? spv::OpAbsUSubINTEL : spv::OpAbsISubINTEL; - break; - - case glslang::EOpAddSaturate: - binOp = isUnsigned ? spv::OpUAddSatINTEL : spv::OpIAddSatINTEL; - break; - - case glslang::EOpSubSaturate: - binOp = isUnsigned ? spv::OpUSubSatINTEL : spv::OpISubSatINTEL; - break; - - case glslang::EOpAverage: - binOp = isUnsigned ? spv::OpUAverageINTEL : spv::OpIAverageINTEL; - break; - - case glslang::EOpAverageRounded: - binOp = isUnsigned ? spv::OpUAverageRoundedINTEL : spv::OpIAverageRoundedINTEL; - break; - - case glslang::EOpMul32x16: - binOp = isUnsigned ? spv::OpUMul32x16INTEL : spv::OpIMul32x16INTEL; - break; - - case glslang::EOpExpectEXT: - binOp = spv::OpExpectKHR; - break; - - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - comparison = true; - break; - default: - break; - } - - // handle mapped binary operations (should be non-comparison) - if (binOp != spv::OpNop) { - assert(comparison == false); - if (builder.isMatrix(left) || builder.isMatrix(right) || - builder.isCooperativeMatrix(left) || builder.isCooperativeMatrix(right)) - return createBinaryMatrixOperation(binOp, decorations, typeId, left, right); - - // No matrix involved; make both operands be the same number of components, if needed - if (needMatchingVectors) - builder.promoteScalar(decorations.precision, left, right); - - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - return builder.setPrecision(result, decorations.precision); - } - - if (! comparison) - return 0; - - // Handle comparison instructions - - if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual) - && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) { - spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual); - decorations.addNonUniform(builder, result); - return result; - } - - switch (op) { - case glslang::EOpLessThan: - if (isFloat) - binOp = spv::OpFOrdLessThan; - else if (isUnsigned) - binOp = spv::OpULessThan; - else - binOp = spv::OpSLessThan; - break; - case glslang::EOpGreaterThan: - if (isFloat) - binOp = spv::OpFOrdGreaterThan; - else if (isUnsigned) - binOp = spv::OpUGreaterThan; - else - binOp = spv::OpSGreaterThan; - break; - case glslang::EOpLessThanEqual: - if (isFloat) - binOp = spv::OpFOrdLessThanEqual; - else if (isUnsigned) - binOp = spv::OpULessThanEqual; - else - binOp = spv::OpSLessThanEqual; - break; - case glslang::EOpGreaterThanEqual: - if (isFloat) - binOp = spv::OpFOrdGreaterThanEqual; - else if (isUnsigned) - binOp = spv::OpUGreaterThanEqual; - else - binOp = spv::OpSGreaterThanEqual; - break; - case glslang::EOpEqual: - case glslang::EOpVectorEqual: - if (isFloat) - binOp = spv::OpFOrdEqual; - else if (isBool) - binOp = spv::OpLogicalEqual; - else - binOp = spv::OpIEqual; - break; - case glslang::EOpNotEqual: - case glslang::EOpVectorNotEqual: - if (isFloat) - binOp = spv::OpFUnordNotEqual; - else if (isBool) - binOp = spv::OpLogicalNotEqual; - else - binOp = spv::OpINotEqual; - break; - default: - break; - } - - if (binOp != spv::OpNop) { - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - return builder.setPrecision(result, decorations.precision); - } - - return 0; -} - -// -// Translate AST matrix operation to SPV operation, already having SPV-based operands/types. -// These can be any of: -// -// matrix * scalar -// scalar * matrix -// matrix * matrix linear algebraic -// matrix * vector -// vector * matrix -// matrix * matrix componentwise -// matrix op matrix op in {+, -, /} -// matrix op scalar op in {+, -, /} -// scalar op matrix op in {+, -, /} -// -spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId, - spv::Id left, spv::Id right) -{ - bool firstClass = true; - - // First, handle first-class matrix operations (* and matrix/scalar) - switch (op) { - case spv::OpFDiv: - if (builder.isMatrix(left) && builder.isScalar(right)) { - // turn matrix / scalar into a multiply... - spv::Id resultType = builder.getTypeId(right); - right = builder.createBinOp(spv::OpFDiv, resultType, builder.makeFpConstant(resultType, 1.0), right); - op = spv::OpMatrixTimesScalar; - } else - firstClass = false; - break; - case spv::OpMatrixTimesScalar: - if (builder.isMatrix(right) || builder.isCooperativeMatrix(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - break; - case spv::OpVectorTimesMatrix: - assert(builder.isVector(left)); - assert(builder.isMatrix(right)); - break; - case spv::OpMatrixTimesVector: - assert(builder.isMatrix(left)); - assert(builder.isVector(right)); - break; - case spv::OpMatrixTimesMatrix: - assert(builder.isMatrix(left)); - assert(builder.isMatrix(right)); - break; - default: - firstClass = false; - break; - } - - if (builder.isCooperativeMatrix(left) || builder.isCooperativeMatrix(right)) - firstClass = true; - - if (firstClass) { - spv::Id result = builder.createBinOp(op, typeId, left, right); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - return builder.setPrecision(result, decorations.precision); - } - - // Handle component-wise +, -, *, %, and / for all combinations of type. - // The result type of all of them is the same type as the (a) matrix operand. - // The algorithm is to: - // - break the matrix(es) into vectors - // - smear any scalar to a vector - // - do vector operations - // - make a matrix out the vector results - switch (op) { - case spv::OpFAdd: - case spv::OpFSub: - case spv::OpFDiv: - case spv::OpFMod: - case spv::OpFMul: - { - // one time set up... - bool leftMat = builder.isMatrix(left); - bool rightMat = builder.isMatrix(right); - unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right); - int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right); - spv::Id scalarType = builder.getScalarTypeId(typeId); - spv::Id vecType = builder.makeVectorType(scalarType, numRows); - std::vector results; - spv::Id smearVec = spv::NoResult; - if (builder.isScalar(left)) - smearVec = builder.smearScalar(decorations.precision, left, vecType); - else if (builder.isScalar(right)) - smearVec = builder.smearScalar(decorations.precision, right, vecType); - - // do each vector op - for (unsigned int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec; - spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec; - spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - results.push_back(builder.setPrecision(result, decorations.precision)); - } - - // put the pieces together - spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - decorations.addNonUniform(builder, result); - return result; - } - default: - assert(0); - return spv::NoResult; - } -} - -spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags, - const glslang::TType &opType) -{ - spv::Op unaryOp = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - switch (op) { - case glslang::EOpNegative: - if (isFloat) { - unaryOp = spv::OpFNegate; - if (builder.isMatrixType(typeId)) - return createUnaryMatrixOperation(unaryOp, decorations, typeId, operand, typeProxy); - } else - unaryOp = spv::OpSNegate; - break; - - case glslang::EOpLogicalNot: - case glslang::EOpVectorLogicalNot: - unaryOp = spv::OpLogicalNot; - break; - case glslang::EOpBitwiseNot: - unaryOp = spv::OpNot; - break; - - case glslang::EOpDeterminant: - libCall = spv::GLSLstd450Determinant; - break; - case glslang::EOpMatrixInverse: - libCall = spv::GLSLstd450MatrixInverse; - break; - case glslang::EOpTranspose: - unaryOp = spv::OpTranspose; - break; - - case glslang::EOpRadians: - libCall = spv::GLSLstd450Radians; - break; - case glslang::EOpDegrees: - libCall = spv::GLSLstd450Degrees; - break; - case glslang::EOpSin: - libCall = spv::GLSLstd450Sin; - break; - case glslang::EOpCos: - libCall = spv::GLSLstd450Cos; - break; - case glslang::EOpTan: - libCall = spv::GLSLstd450Tan; - break; - case glslang::EOpAcos: - libCall = spv::GLSLstd450Acos; - break; - case glslang::EOpAsin: - libCall = spv::GLSLstd450Asin; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan; - break; - - case glslang::EOpAcosh: - libCall = spv::GLSLstd450Acosh; - break; - case glslang::EOpAsinh: - libCall = spv::GLSLstd450Asinh; - break; - case glslang::EOpAtanh: - libCall = spv::GLSLstd450Atanh; - break; - case glslang::EOpTanh: - libCall = spv::GLSLstd450Tanh; - break; - case glslang::EOpCosh: - libCall = spv::GLSLstd450Cosh; - break; - case glslang::EOpSinh: - libCall = spv::GLSLstd450Sinh; - break; - - case glslang::EOpLength: - libCall = spv::GLSLstd450Length; - break; - case glslang::EOpNormalize: - libCall = spv::GLSLstd450Normalize; - break; - - case glslang::EOpExp: - libCall = spv::GLSLstd450Exp; - break; - case glslang::EOpLog: - libCall = spv::GLSLstd450Log; - break; - case glslang::EOpExp2: - libCall = spv::GLSLstd450Exp2; - break; - case glslang::EOpLog2: - libCall = spv::GLSLstd450Log2; - break; - case glslang::EOpSqrt: - libCall = spv::GLSLstd450Sqrt; - break; - case glslang::EOpInverseSqrt: - libCall = spv::GLSLstd450InverseSqrt; - break; - - case glslang::EOpFloor: - libCall = spv::GLSLstd450Floor; - break; - case glslang::EOpTrunc: - libCall = spv::GLSLstd450Trunc; - break; - case glslang::EOpRound: - libCall = spv::GLSLstd450Round; - break; - case glslang::EOpRoundEven: - libCall = spv::GLSLstd450RoundEven; - break; - case glslang::EOpCeil: - libCall = spv::GLSLstd450Ceil; - break; - case glslang::EOpFract: - libCall = spv::GLSLstd450Fract; - break; - - case glslang::EOpIsNan: - unaryOp = spv::OpIsNan; - break; - case glslang::EOpIsInf: - unaryOp = spv::OpIsInf; - break; - case glslang::EOpIsFinite: - unaryOp = spv::OpIsFinite; - break; - - case glslang::EOpFloatBitsToInt: - case glslang::EOpFloatBitsToUint: - case glslang::EOpIntBitsToFloat: - case glslang::EOpUintBitsToFloat: - case glslang::EOpDoubleBitsToInt64: - case glslang::EOpDoubleBitsToUint64: - case glslang::EOpInt64BitsToDouble: - case glslang::EOpUint64BitsToDouble: - case glslang::EOpFloat16BitsToInt16: - case glslang::EOpFloat16BitsToUint16: - case glslang::EOpInt16BitsToFloat16: - case glslang::EOpUint16BitsToFloat16: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpPackSnorm2x16: - libCall = spv::GLSLstd450PackSnorm2x16; - break; - case glslang::EOpUnpackSnorm2x16: - libCall = spv::GLSLstd450UnpackSnorm2x16; - break; - case glslang::EOpPackUnorm2x16: - libCall = spv::GLSLstd450PackUnorm2x16; - break; - case glslang::EOpUnpackUnorm2x16: - libCall = spv::GLSLstd450UnpackUnorm2x16; - break; - case glslang::EOpPackHalf2x16: - libCall = spv::GLSLstd450PackHalf2x16; - break; - case glslang::EOpUnpackHalf2x16: - libCall = spv::GLSLstd450UnpackHalf2x16; - break; - case glslang::EOpPackSnorm4x8: - libCall = spv::GLSLstd450PackSnorm4x8; - break; - case glslang::EOpUnpackSnorm4x8: - libCall = spv::GLSLstd450UnpackSnorm4x8; - break; - case glslang::EOpPackUnorm4x8: - libCall = spv::GLSLstd450PackUnorm4x8; - break; - case glslang::EOpUnpackUnorm4x8: - libCall = spv::GLSLstd450UnpackUnorm4x8; - break; - case glslang::EOpPackDouble2x32: - libCall = spv::GLSLstd450PackDouble2x32; - break; - case glslang::EOpUnpackDouble2x32: - libCall = spv::GLSLstd450UnpackDouble2x32; - break; - - case glslang::EOpPackInt2x32: - case glslang::EOpUnpackInt2x32: - case glslang::EOpPackUint2x32: - case glslang::EOpUnpackUint2x32: - case glslang::EOpPack16: - case glslang::EOpPack32: - case glslang::EOpPack64: - case glslang::EOpUnpack32: - case glslang::EOpUnpack16: - case glslang::EOpUnpack8: - case glslang::EOpPackInt2x16: - case glslang::EOpUnpackInt2x16: - case glslang::EOpPackUint2x16: - case glslang::EOpUnpackUint2x16: - case glslang::EOpPackInt4x16: - case glslang::EOpUnpackInt4x16: - case glslang::EOpPackUint4x16: - case glslang::EOpUnpackUint4x16: - case glslang::EOpPackFloat2x16: - case glslang::EOpUnpackFloat2x16: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpDPdx: - unaryOp = spv::OpDPdx; - break; - case glslang::EOpDPdy: - unaryOp = spv::OpDPdy; - break; - case glslang::EOpFwidth: - unaryOp = spv::OpFwidth; - break; - - case glslang::EOpAny: - unaryOp = spv::OpAny; - break; - case glslang::EOpAll: - unaryOp = spv::OpAll; - break; - - case glslang::EOpAbs: - if (isFloat) - libCall = spv::GLSLstd450FAbs; - else - libCall = spv::GLSLstd450SAbs; - break; - case glslang::EOpSign: - if (isFloat) - libCall = spv::GLSLstd450FSign; - else - libCall = spv::GLSLstd450SSign; - break; - - case glslang::EOpDPdxFine: - unaryOp = spv::OpDPdxFine; - break; - case glslang::EOpDPdyFine: - unaryOp = spv::OpDPdyFine; - break; - case glslang::EOpFwidthFine: - unaryOp = spv::OpFwidthFine; - break; - case glslang::EOpDPdxCoarse: - unaryOp = spv::OpDPdxCoarse; - break; - case glslang::EOpDPdyCoarse: - unaryOp = spv::OpDPdyCoarse; - break; - case glslang::EOpFwidthCoarse: - unaryOp = spv::OpFwidthCoarse; - break; - case glslang::EOpRayQueryProceed: - unaryOp = spv::OpRayQueryProceedKHR; - break; - case glslang::EOpRayQueryGetRayTMin: - unaryOp = spv::OpRayQueryGetRayTMinKHR; - break; - case glslang::EOpRayQueryGetRayFlags: - unaryOp = spv::OpRayQueryGetRayFlagsKHR; - break; - case glslang::EOpRayQueryGetWorldRayOrigin: - unaryOp = spv::OpRayQueryGetWorldRayOriginKHR; - break; - case glslang::EOpRayQueryGetWorldRayDirection: - unaryOp = spv::OpRayQueryGetWorldRayDirectionKHR; - break; - case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: - unaryOp = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; - break; - case glslang::EOpInterpolateAtCentroid: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - libCall = spv::GLSLstd450InterpolateAtCentroid; - break; - case glslang::EOpAtomicCounterIncrement: - case glslang::EOpAtomicCounterDecrement: - case glslang::EOpAtomicCounter: - { - // Handle all of the atomics in one place, in createAtomicOperation() - std::vector operands; - operands.push_back(operand); - return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy, lvalueCoherentFlags, opType); - } - - case glslang::EOpBitFieldReverse: - unaryOp = spv::OpBitReverse; - break; - case glslang::EOpBitCount: - unaryOp = spv::OpBitCount; - break; - case glslang::EOpFindLSB: - libCall = spv::GLSLstd450FindILsb; - break; - case glslang::EOpFindMSB: - if (isUnsigned) - libCall = spv::GLSLstd450FindUMsb; - else - libCall = spv::GLSLstd450FindSMsb; - break; - - case glslang::EOpCountLeadingZeros: - builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); - builder.addExtension("SPV_INTEL_shader_integer_functions2"); - unaryOp = spv::OpUCountLeadingZerosINTEL; - break; - - case glslang::EOpCountTrailingZeros: - builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); - builder.addExtension("SPV_INTEL_shader_integer_functions2"); - unaryOp = spv::OpUCountTrailingZerosINTEL; - break; - - case glslang::EOpBallot: - case glslang::EOpReadFirstInvocation: - case glslang::EOpAnyInvocation: - case glslang::EOpAllInvocations: - case glslang::EOpAllInvocationsEqual: - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - { - std::vector operands; - operands.push_back(operand); - return createInvocationsOperation(op, typeId, operands, typeProxy); - } - case glslang::EOpSubgroupAll: - case glslang::EOpSubgroupAny: - case glslang::EOpSubgroupAllEqual: - case glslang::EOpSubgroupBroadcastFirst: - case glslang::EOpSubgroupBallot: - case glslang::EOpSubgroupInverseBallot: - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupBallotFindLSB: - case glslang::EOpSubgroupBallotFindMSB: - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: - case glslang::EOpSubgroupQuadAll: - case glslang::EOpSubgroupQuadAny: { - std::vector operands; - operands.push_back(operand); - return createSubgroupOperation(op, typeId, operands, typeProxy); - } - case glslang::EOpMbcnt: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::MbcntAMD; - break; - - case glslang::EOpCubeFaceIndex: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceIndexAMD; - break; - - case glslang::EOpCubeFaceCoord: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceCoordAMD; - break; - case glslang::EOpSubgroupPartition: - unaryOp = spv::OpGroupNonUniformPartitionNV; - break; - case glslang::EOpConstructReference: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpConvUint64ToAccStruct: - case glslang::EOpConvUvec2ToAccStruct: - unaryOp = spv::OpConvertUToAccelerationStructureKHR; - break; - - case glslang::EOpHitObjectIsEmptyNV: - unaryOp = spv::OpHitObjectIsEmptyNV; - break; - - case glslang::EOpHitObjectIsMissNV: - unaryOp = spv::OpHitObjectIsMissNV; - break; - - case glslang::EOpHitObjectIsHitNV: - unaryOp = spv::OpHitObjectIsHitNV; - break; - - case glslang::EOpHitObjectGetObjectRayOriginNV: - unaryOp = spv::OpHitObjectGetObjectRayOriginNV; - break; - - case glslang::EOpHitObjectGetObjectRayDirectionNV: - unaryOp = spv::OpHitObjectGetObjectRayDirectionNV; - break; - - case glslang::EOpHitObjectGetWorldRayOriginNV: - unaryOp = spv::OpHitObjectGetWorldRayOriginNV; - break; - - case glslang::EOpHitObjectGetWorldRayDirectionNV: - unaryOp = spv::OpHitObjectGetWorldRayDirectionNV; - break; - - case glslang::EOpHitObjectGetObjectToWorldNV: - unaryOp = spv::OpHitObjectGetObjectToWorldNV; - break; - - case glslang::EOpHitObjectGetWorldToObjectNV: - unaryOp = spv::OpHitObjectGetWorldToObjectNV; - break; - - case glslang::EOpHitObjectGetRayTMinNV: - unaryOp = spv::OpHitObjectGetRayTMinNV; - break; - - case glslang::EOpHitObjectGetRayTMaxNV: - unaryOp = spv::OpHitObjectGetRayTMaxNV; - break; - - case glslang::EOpHitObjectGetPrimitiveIndexNV: - unaryOp = spv::OpHitObjectGetPrimitiveIndexNV; - break; - - case glslang::EOpHitObjectGetInstanceIdNV: - unaryOp = spv::OpHitObjectGetInstanceIdNV; - break; - - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - unaryOp = spv::OpHitObjectGetInstanceCustomIndexNV; - break; - - case glslang::EOpHitObjectGetGeometryIndexNV: - unaryOp = spv::OpHitObjectGetGeometryIndexNV; - break; - - case glslang::EOpHitObjectGetHitKindNV: - unaryOp = spv::OpHitObjectGetHitKindNV; - break; - - case glslang::EOpHitObjectGetCurrentTimeNV: - unaryOp = spv::OpHitObjectGetCurrentTimeNV; - break; - - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - unaryOp = spv::OpHitObjectGetShaderBindingTableRecordIndexNV; - break; - - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - unaryOp = spv::OpHitObjectGetShaderRecordBufferHandleNV; - break; - - case glslang::EOpFetchMicroTriangleVertexPositionNV: - unaryOp = spv::OpFetchMicroTriangleVertexPositionNV; - break; - - case glslang::EOpFetchMicroTriangleVertexBarycentricNV: - unaryOp = spv::OpFetchMicroTriangleVertexBarycentricNV; - break; - - case glslang::EOpCopyObject: - unaryOp = spv::OpCopyObject; - break; - - case glslang::EOpDepthAttachmentReadEXT: - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.addCapability(spv::CapabilityTileImageDepthReadAccessEXT); - unaryOp = spv::OpDepthAttachmentReadEXT; - decorations.precision = spv::NoPrecision; - break; - case glslang::EOpStencilAttachmentReadEXT: - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.addCapability(spv::CapabilityTileImageStencilReadAccessEXT); - unaryOp = spv::OpStencilAttachmentReadEXT; - decorations.precision = spv::DecorationRelaxedPrecision; - break; - - default: - return 0; - } - - spv::Id id; - if (libCall >= 0) { - std::vector args; - args.push_back(operand); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, args); - } else { - id = builder.createUnaryOp(unaryOp, typeId, operand); - } - - decorations.addNoContraction(builder, id); - decorations.addNonUniform(builder, id); - return builder.setPrecision(id, decorations.precision); -} - -// Create a unary operation on a matrix -spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType /* typeProxy */) -{ - // Handle unary operations vector by vector. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the matrix into vectors - // - apply the operation to each vector - // - make a matrix out the vector results - - // get the types sorted out - int numCols = builder.getNumColumns(operand); - int numRows = builder.getNumRows(operand); - spv::Id srcVecType = builder.makeVectorType(builder.getScalarTypeId(builder.getTypeId(operand)), numRows); - spv::Id destVecType = builder.makeVectorType(builder.getScalarTypeId(typeId), numRows); - std::vector results; - - // do each vector op - for (int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes); - spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec); - decorations.addNoContraction(builder, destVec); - decorations.addNonUniform(builder, destVec); - results.push_back(builder.setPrecision(destVec, decorations.precision)); - } - - // put the pieces together - spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - decorations.addNonUniform(builder, result); - return result; -} - -// For converting integers where both the bitwidth and the signedness could -// change, but only do the width change here. The caller is still responsible -// for the signedness conversion. -// destType is the final type that will be converted to, but this function -// may only be doing part of that conversion. -spv::Id TGlslangToSpvTraverser::createIntWidthConversion(spv::Id operand, int vectorSize, spv::Id destType, - glslang::TBasicType resultBasicType, glslang::TBasicType operandBasicType) -{ - // Get the result type width, based on the type to convert to. - int width = GetNumBits(resultBasicType); - - // Get the conversion operation and result type, - // based on the target width, but the source type. - spv::Id type = spv::NoType; - spv::Op convOp = spv::OpNop; - if (isTypeSignedInt(operandBasicType)) { - convOp = spv::OpSConvert; - type = builder.makeIntType(width); - } else { - convOp = spv::OpUConvert; - type = builder.makeUintType(width); - } - - if (vectorSize > 0) - type = builder.makeVectorType(type, vectorSize); - else if (builder.getOpCode(destType) == spv::OpTypeCooperativeMatrixKHR || - builder.getOpCode(destType) == spv::OpTypeCooperativeMatrixNV) { - - type = builder.makeCooperativeMatrixTypeWithSameShape(type, destType); - } - - return builder.createUnaryOp(convOp, type, operand); -} - -spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecorations& decorations, spv::Id destType, - spv::Id operand, glslang::TBasicType resultBasicType, glslang::TBasicType operandBasicType) -{ - spv::Op convOp = spv::OpNop; - spv::Id zero = 0; - spv::Id one = 0; - - int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0; - - if (IsOpNumericConv(op)) { - if (isTypeSignedInt(operandBasicType) && isTypeFloat(resultBasicType)) { - convOp = spv::OpConvertSToF; - } - if (isTypeUnsignedInt(operandBasicType) && isTypeFloat(resultBasicType)) { - convOp = spv::OpConvertUToF; - } - if (isTypeFloat(operandBasicType) && isTypeSignedInt(resultBasicType)) { - convOp = spv::OpConvertFToS; - } - if (isTypeFloat(operandBasicType) && isTypeUnsignedInt(resultBasicType)) { - convOp = spv::OpConvertFToU; - } - if (isTypeSignedInt(operandBasicType) && isTypeSignedInt(resultBasicType)) { - convOp = spv::OpSConvert; - } - if (isTypeUnsignedInt(operandBasicType) && isTypeUnsignedInt(resultBasicType)) { - convOp = spv::OpUConvert; - } - if (isTypeFloat(operandBasicType) && isTypeFloat(resultBasicType)) { - convOp = spv::OpFConvert; - if (builder.isMatrixType(destType)) - return createUnaryMatrixOperation(convOp, decorations, destType, operand, operandBasicType); - } - if (isTypeInt(operandBasicType) && isTypeInt(resultBasicType) && - isTypeUnsignedInt(operandBasicType) != isTypeUnsignedInt(resultBasicType)) { - - if (GetNumBits(operandBasicType) != GetNumBits(resultBasicType)) { - // OpSConvert/OpUConvert + OpBitCast - operand = createIntWidthConversion(operand, vectorSize, destType, resultBasicType, operandBasicType); - } - - if (builder.isInSpecConstCodeGenMode()) { - uint32_t bits = GetNumBits(resultBasicType); - spv::Id zeroType = builder.makeUintType(bits); - if (bits == 64) { - zero = builder.makeInt64Constant(zeroType, 0, false); - } else { - zero = builder.makeIntConstant(zeroType, 0, false); - } - zero = makeSmearedConstant(zero, vectorSize); - // Use OpIAdd, instead of OpBitcast to do the conversion when - // generating for OpSpecConstantOp instruction. - return builder.createBinOp(spv::OpIAdd, destType, operand, zero); - } - // For normal run-time conversion instruction, use OpBitcast. - convOp = spv::OpBitcast; - } - if (resultBasicType == glslang::EbtBool) { - uint32_t bits = GetNumBits(operandBasicType); - if (isTypeInt(operandBasicType)) { - spv::Id zeroType = builder.makeUintType(bits); - if (bits == 64) { - zero = builder.makeInt64Constant(zeroType, 0, false); - } else { - zero = builder.makeIntConstant(zeroType, 0, false); - } - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - } else { - assert(isTypeFloat(operandBasicType)); - if (bits == 64) { - zero = builder.makeDoubleConstant(0.0); - } else if (bits == 32) { - zero = builder.makeFloatConstant(0.0); - } else { - assert(bits == 16); - zero = builder.makeFloat16Constant(0.0); - } - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFUnordNotEqual, destType, operand, zero); - } - } - if (operandBasicType == glslang::EbtBool) { - uint32_t bits = GetNumBits(resultBasicType); - convOp = spv::OpSelect; - if (isTypeInt(resultBasicType)) { - spv::Id zeroType = isTypeSignedInt(resultBasicType) ? builder.makeIntType(bits) : builder.makeUintType(bits); - if (bits == 64) { - zero = builder.makeInt64Constant(zeroType, 0, false); - one = builder.makeInt64Constant(zeroType, 1, false); - } else { - zero = builder.makeIntConstant(zeroType, 0, false); - one = builder.makeIntConstant(zeroType, 1, false); - } - } else { - assert(isTypeFloat(resultBasicType)); - if (bits == 64) { - zero = builder.makeDoubleConstant(0.0); - one = builder.makeDoubleConstant(1.0); - } else if (bits == 32) { - zero = builder.makeFloatConstant(0.0); - one = builder.makeFloatConstant(1.0); - } else { - assert(bits == 16); - zero = builder.makeFloat16Constant(0.0); - one = builder.makeFloat16Constant(1.0); - } - } - } - } - - if (convOp == spv::OpNop) { - switch (op) { - case glslang::EOpConvUint64ToPtr: - convOp = spv::OpConvertUToPtr; - break; - case glslang::EOpConvPtrToUint64: - convOp = spv::OpConvertPtrToU; - break; - case glslang::EOpConvPtrToUvec2: - case glslang::EOpConvUvec2ToPtr: - convOp = spv::OpBitcast; - break; - - default: - break; - } - } - - spv::Id result = 0; - if (convOp == spv::OpNop) - return result; - - if (convOp == spv::OpSelect) { - zero = makeSmearedConstant(zero, vectorSize); - one = makeSmearedConstant(one, vectorSize); - result = builder.createTriOp(convOp, destType, operand, one, zero); - } else - result = builder.createUnaryOp(convOp, destType, operand); - - result = builder.setPrecision(result, decorations.precision); - decorations.addNonUniform(builder, result); - return result; -} - -spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize) -{ - if (vectorSize == 0) - return constant; - - spv::Id vectorTypeId = builder.makeVectorType(builder.getTypeId(constant), vectorSize); - std::vector components; - for (int c = 0; c < vectorSize; ++c) - components.push_back(constant); - return builder.makeCompositeConstant(vectorTypeId, components); -} - -// For glslang ops that map to SPV atomic opCodes -spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, - spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, - const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags, const glslang::TType &opType) -{ - spv::Op opCode = spv::OpNop; - - switch (op) { - case glslang::EOpAtomicAdd: - case glslang::EOpImageAtomicAdd: - case glslang::EOpAtomicCounterAdd: - opCode = spv::OpAtomicIAdd; - if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { - opCode = spv::OpAtomicFAddEXT; - if (typeProxy == glslang::EbtFloat16 && - (opType.getVectorSize() == 2 || opType.getVectorSize() == 4)) { - builder.addExtension(spv::E_SPV_NV_shader_atomic_fp16_vector); - builder.addCapability(spv::CapabilityAtomicFloat16VectorNV); - } else { - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_add); - if (typeProxy == glslang::EbtFloat16) { - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float16_add); - builder.addCapability(spv::CapabilityAtomicFloat16AddEXT); - } else if (typeProxy == glslang::EbtFloat) { - builder.addCapability(spv::CapabilityAtomicFloat32AddEXT); - } else { - builder.addCapability(spv::CapabilityAtomicFloat64AddEXT); - } - } - } - break; - case glslang::EOpAtomicSubtract: - case glslang::EOpAtomicCounterSubtract: - opCode = spv::OpAtomicISub; - break; - case glslang::EOpAtomicMin: - case glslang::EOpImageAtomicMin: - case glslang::EOpAtomicCounterMin: - if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { - opCode = spv::OpAtomicFMinEXT; - if (typeProxy == glslang::EbtFloat16 && - (opType.getVectorSize() == 2 || opType.getVectorSize() == 4)) { - builder.addExtension(spv::E_SPV_NV_shader_atomic_fp16_vector); - builder.addCapability(spv::CapabilityAtomicFloat16VectorNV); - } else { - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max); - if (typeProxy == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT); - else if (typeProxy == glslang::EbtFloat) - builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT); - else - builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT); - } - } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) { - opCode = spv::OpAtomicUMin; - } else { - opCode = spv::OpAtomicSMin; - } - break; - case glslang::EOpAtomicMax: - case glslang::EOpImageAtomicMax: - case glslang::EOpAtomicCounterMax: - if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { - opCode = spv::OpAtomicFMaxEXT; - if (typeProxy == glslang::EbtFloat16 && - (opType.getVectorSize() == 2 || opType.getVectorSize() == 4)) { - builder.addExtension(spv::E_SPV_NV_shader_atomic_fp16_vector); - builder.addCapability(spv::CapabilityAtomicFloat16VectorNV); - } else { - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max); - if (typeProxy == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT); - else if (typeProxy == glslang::EbtFloat) - builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT); - else - builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT); - } - } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) { - opCode = spv::OpAtomicUMax; - } else { - opCode = spv::OpAtomicSMax; - } - break; - case glslang::EOpAtomicAnd: - case glslang::EOpImageAtomicAnd: - case glslang::EOpAtomicCounterAnd: - opCode = spv::OpAtomicAnd; - break; - case glslang::EOpAtomicOr: - case glslang::EOpImageAtomicOr: - case glslang::EOpAtomicCounterOr: - opCode = spv::OpAtomicOr; - break; - case glslang::EOpAtomicXor: - case glslang::EOpImageAtomicXor: - case glslang::EOpAtomicCounterXor: - opCode = spv::OpAtomicXor; - break; - case glslang::EOpAtomicExchange: - case glslang::EOpImageAtomicExchange: - case glslang::EOpAtomicCounterExchange: - if ((typeProxy == glslang::EbtFloat16) && - (opType.getVectorSize() == 2 || opType.getVectorSize() == 4)) { - builder.addExtension(spv::E_SPV_NV_shader_atomic_fp16_vector); - builder.addCapability(spv::CapabilityAtomicFloat16VectorNV); - } - - opCode = spv::OpAtomicExchange; - break; - case glslang::EOpAtomicCompSwap: - case glslang::EOpImageAtomicCompSwap: - case glslang::EOpAtomicCounterCompSwap: - opCode = spv::OpAtomicCompareExchange; - break; - case glslang::EOpAtomicCounterIncrement: - opCode = spv::OpAtomicIIncrement; - break; - case glslang::EOpAtomicCounterDecrement: - opCode = spv::OpAtomicIDecrement; - break; - case glslang::EOpAtomicCounter: - case glslang::EOpImageAtomicLoad: - case glslang::EOpAtomicLoad: - opCode = spv::OpAtomicLoad; - break; - case glslang::EOpAtomicStore: - case glslang::EOpImageAtomicStore: - opCode = spv::OpAtomicStore; - break; - default: - assert(0); - break; - } - - if (typeProxy == glslang::EbtInt64 || typeProxy == glslang::EbtUint64) - builder.addCapability(spv::CapabilityInt64Atomics); - - // Sort out the operands - // - mapping from glslang -> SPV - // - there are extra SPV operands that are optional in glslang - // - compare-exchange swaps the value and comparator - // - compare-exchange has an extra memory semantics - // - EOpAtomicCounterDecrement needs a post decrement - spv::Id pointerId = 0, compareId = 0, valueId = 0; - // scope defaults to Device in the old model, QueueFamilyKHR in the new model - spv::Id scopeId; - if (glslangIntermediate->usingVulkanMemoryModel()) { - scopeId = builder.makeUintConstant(spv::ScopeQueueFamilyKHR); - } else { - scopeId = builder.makeUintConstant(spv::ScopeDevice); - } - // semantics default to relaxed - spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && - glslangIntermediate->usingVulkanMemoryModel() ? - spv::MemorySemanticsVolatileMask : - spv::MemorySemanticsMaskNone); - spv::Id semanticsId2 = semanticsId; - - pointerId = operands[0]; - if (opCode == spv::OpAtomicIIncrement || opCode == spv::OpAtomicIDecrement) { - // no additional operands - } else if (opCode == spv::OpAtomicCompareExchange) { - compareId = operands[1]; - valueId = operands[2]; - if (operands.size() > 3) { - scopeId = operands[3]; - semanticsId = builder.makeUintConstant( - builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5])); - semanticsId2 = builder.makeUintConstant( - builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7])); - } - } else if (opCode == spv::OpAtomicLoad) { - if (operands.size() > 1) { - scopeId = operands[1]; - semanticsId = builder.makeUintConstant( - builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3])); - } - } else { - // atomic store or RMW - valueId = operands[1]; - if (operands.size() > 2) { - scopeId = operands[2]; - semanticsId = builder.makeUintConstant - (builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4])); - } - } - - // Check for capabilities - unsigned semanticsImmediate = builder.getConstantScalar(semanticsId) | builder.getConstantScalar(semanticsId2); - if (semanticsImmediate & (spv::MemorySemanticsMakeAvailableKHRMask | - spv::MemorySemanticsMakeVisibleKHRMask | - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsVolatileMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - if (builder.getConstantScalar(scopeId) == spv::ScopeQueueFamily) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - - std::vector spvAtomicOperands; // hold the spv operands - spvAtomicOperands.reserve(6); - spvAtomicOperands.push_back(pointerId); - spvAtomicOperands.push_back(scopeId); - spvAtomicOperands.push_back(semanticsId); - if (opCode == spv::OpAtomicCompareExchange) { - spvAtomicOperands.push_back(semanticsId2); - spvAtomicOperands.push_back(valueId); - spvAtomicOperands.push_back(compareId); - } else if (opCode != spv::OpAtomicLoad && opCode != spv::OpAtomicIIncrement && opCode != spv::OpAtomicIDecrement) { - spvAtomicOperands.push_back(valueId); - } - - if (opCode == spv::OpAtomicStore) { - builder.createNoResultOp(opCode, spvAtomicOperands); - return 0; - } else { - spv::Id resultId = builder.createOp(opCode, typeId, spvAtomicOperands); - - // GLSL and HLSL atomic-counter decrement return post-decrement value, - // while SPIR-V returns pre-decrement value. Translate between these semantics. - if (op == glslang::EOpAtomicCounterDecrement) - resultId = builder.createBinOp(spv::OpISub, typeId, resultId, builder.makeIntConstant(1)); - - return resultId; - } -} - -// Create group invocation operations. -spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - spv::Op opCode = spv::OpNop; - std::vector spvGroupOperands; - spv::GroupOperation groupOperation = spv::GroupOperationMax; - - if (op == glslang::EOpBallot || op == glslang::EOpReadFirstInvocation || - op == glslang::EOpReadInvocation) { - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - } else if (op == glslang::EOpAnyInvocation || - op == glslang::EOpAllInvocations || - op == glslang::EOpAllInvocationsEqual) { - builder.addExtension(spv::E_SPV_KHR_subgroup_vote); - builder.addCapability(spv::CapabilitySubgroupVoteKHR); - } else { - builder.addCapability(spv::CapabilityGroups); - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpAddInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpAddInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform || - op == glslang::EOpAddInvocationsExclusiveScanNonUniform) - builder.addExtension(spv::E_SPV_AMD_shader_ballot); - - switch (op) { - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - groupOperation = spv::GroupOperationReduce; - break; - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - groupOperation = spv::GroupOperationInclusiveScan; - break; - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - groupOperation = spv::GroupOperationExclusiveScan; - break; - default: - break; - } - spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(scope); - if (groupOperation != spv::GroupOperationMax) { - spv::IdImmediate groupOp = { false, (unsigned)groupOperation }; - spvGroupOperands.push_back(groupOp); - } - } - - for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) { - spv::IdImmediate op = { true, *opIt }; - spvGroupOperands.push_back(op); - } - - switch (op) { - case glslang::EOpAnyInvocation: - opCode = spv::OpSubgroupAnyKHR; - break; - case glslang::EOpAllInvocations: - opCode = spv::OpSubgroupAllKHR; - break; - case glslang::EOpAllInvocationsEqual: - opCode = spv::OpSubgroupAllEqualKHR; - break; - case glslang::EOpReadInvocation: - opCode = spv::OpSubgroupReadInvocationKHR; - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - break; - case glslang::EOpReadFirstInvocation: - opCode = spv::OpSubgroupFirstInvocationKHR; - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - break; - case glslang::EOpBallot: - { - // NOTE: According to the spec, the result type of "OpSubgroupBallotKHR" must be a 4 component vector of 32 - // bit integer types. The GLSL built-in function "ballotARB()" assumes the maximum number of invocations in - // a subgroup is 64. Thus, we have to convert uvec4.xy to uint64_t as follow: - // - // result = Bitcast(SubgroupBallotKHR(Predicate).xy) - // - spv::Id uintType = builder.makeUintType(32); - spv::Id uvec4Type = builder.makeVectorType(uintType, 4); - spv::Id result = builder.createOp(spv::OpSubgroupBallotKHR, uvec4Type, spvGroupOperands); - - std::vector components; - components.push_back(builder.createCompositeExtract(result, uintType, 0)); - components.push_back(builder.createCompositeExtract(result, uintType, 1)); - - spv::Id uvec2Type = builder.makeVectorType(uintType, 2); - return builder.createUnaryOp(spv::OpBitcast, typeId, - builder.createCompositeConstruct(uvec2Type, components)); - } - - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - if (op == glslang::EOpMinInvocations || - op == glslang::EOpMinInvocationsInclusiveScan || - op == glslang::EOpMinInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMin; - else { - if (isUnsigned) - opCode = spv::OpGroupUMin; - else - opCode = spv::OpGroupSMin; - } - } else if (op == glslang::EOpMaxInvocations || - op == glslang::EOpMaxInvocationsInclusiveScan || - op == glslang::EOpMaxInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMax; - else { - if (isUnsigned) - opCode = spv::OpGroupUMax; - else - opCode = spv::OpGroupSMax; - } - } else { - if (isFloat) - opCode = spv::OpGroupFAdd; - else - opCode = spv::OpGroupIAdd; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMinNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMinNonUniformAMD; - else - opCode = spv::OpGroupSMinNonUniformAMD; - } - } - else if (op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMaxNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMaxNonUniformAMD; - else - opCode = spv::OpGroupSMaxNonUniformAMD; - } - } - else { - if (isFloat) - opCode = spv::OpGroupFAddNonUniformAMD; - else - opCode = spv::OpGroupIAddNonUniformAMD; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; - default: - logger->missingFunctionality("invocation operation"); - return spv::NoResult; - } - - assert(opCode != spv::OpNop); - return builder.createOp(opCode, typeId, spvGroupOperands); -} - -// Create group invocation operations on a vector -spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, - spv::Id typeId, std::vector& operands) -{ - assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || - op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || - op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || - op == spv::OpSubgroupReadInvocationKHR || op == spv::OpSubgroupFirstInvocationKHR || - op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || - op == spv::OpGroupSMinNonUniformAMD || - op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || - op == spv::OpGroupSMaxNonUniformAMD || - op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD); - - // Handle group invocation operations scalar by scalar. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the vector into scalars - // - apply the operation to each scalar - // - make a vector out the scalar results - - // get the types sorted out - int numComponents = builder.getNumComponents(operands[0]); - spv::Id scalarType = builder.getScalarTypeId(builder.getTypeId(operands[0])); - std::vector results; - - // do each scalar op - for (int comp = 0; comp < numComponents; ++comp) { - std::vector indexes; - indexes.push_back(comp); - spv::IdImmediate scalar = { true, builder.createCompositeExtract(operands[0], scalarType, indexes) }; - std::vector spvGroupOperands; - if (op == spv::OpSubgroupReadInvocationKHR) { - spvGroupOperands.push_back(scalar); - spv::IdImmediate operand = { true, operands[1] }; - spvGroupOperands.push_back(operand); - } else if (op == spv::OpSubgroupFirstInvocationKHR) { - spvGroupOperands.push_back(scalar); - } else if (op == spv::OpGroupBroadcast) { - spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(scope); - spvGroupOperands.push_back(scalar); - spv::IdImmediate operand = { true, operands[1] }; - spvGroupOperands.push_back(operand); - } else { - spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(scope); - spv::IdImmediate groupOp = { false, (unsigned)groupOperation }; - spvGroupOperands.push_back(groupOp); - spvGroupOperands.push_back(scalar); - } - - results.push_back(builder.createOp(op, scalarType, spvGroupOperands)); - } - - // put the pieces together - return builder.createCompositeConstruct(typeId, results); -} - -// Create subgroup invocation operations. -spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy) -{ - // Add the required capabilities. - switch (op) { - case glslang::EOpSubgroupElect: - builder.addCapability(spv::CapabilityGroupNonUniform); - break; - case glslang::EOpSubgroupQuadAll: - case glslang::EOpSubgroupQuadAny: - builder.addExtension(spv::E_SPV_KHR_quad_control); - builder.addCapability(spv::CapabilityQuadControlKHR); - [[fallthrough]]; - case glslang::EOpSubgroupAll: - case glslang::EOpSubgroupAny: - case glslang::EOpSubgroupAllEqual: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformVote); - break; - case glslang::EOpSubgroupBroadcast: - case glslang::EOpSubgroupBroadcastFirst: - case glslang::EOpSubgroupBallot: - case glslang::EOpSubgroupInverseBallot: - case glslang::EOpSubgroupBallotBitExtract: - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupBallotFindLSB: - case glslang::EOpSubgroupBallotFindMSB: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - break; - case glslang::EOpSubgroupRotate: - case glslang::EOpSubgroupClusteredRotate: - builder.addExtension(spv::E_SPV_KHR_subgroup_rotate); - builder.addCapability(spv::CapabilityGroupNonUniformRotateKHR); - break; - case glslang::EOpSubgroupShuffle: - case glslang::EOpSubgroupShuffleXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformShuffle); - break; - case glslang::EOpSubgroupShuffleUp: - case glslang::EOpSubgroupShuffleDown: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformShuffleRelative); - break; - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformArithmetic); - break; - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformClustered); - break; - case glslang::EOpSubgroupQuadBroadcast: - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformQuad); - break; - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - builder.addExtension(spv::E_SPV_NV_shader_subgroup_partitioned); - builder.addCapability(spv::CapabilityGroupNonUniformPartitionedNV); - break; - default: assert(0 && "Unhandled subgroup operation!"); - } - - - const bool isUnsigned = isTypeUnsignedInt(typeProxy); - const bool isFloat = isTypeFloat(typeProxy); - const bool isBool = typeProxy == glslang::EbtBool; - - spv::Op opCode = spv::OpNop; - - // Figure out which opcode to use. - switch (op) { - case glslang::EOpSubgroupElect: opCode = spv::OpGroupNonUniformElect; break; - case glslang::EOpSubgroupQuadAll: opCode = spv::OpGroupNonUniformQuadAllKHR; break; - case glslang::EOpSubgroupAll: opCode = spv::OpGroupNonUniformAll; break; - case glslang::EOpSubgroupQuadAny: opCode = spv::OpGroupNonUniformQuadAnyKHR; break; - case glslang::EOpSubgroupAny: opCode = spv::OpGroupNonUniformAny; break; - case glslang::EOpSubgroupAllEqual: opCode = spv::OpGroupNonUniformAllEqual; break; - case glslang::EOpSubgroupBroadcast: opCode = spv::OpGroupNonUniformBroadcast; break; - case glslang::EOpSubgroupBroadcastFirst: opCode = spv::OpGroupNonUniformBroadcastFirst; break; - case glslang::EOpSubgroupBallot: opCode = spv::OpGroupNonUniformBallot; break; - case glslang::EOpSubgroupInverseBallot: opCode = spv::OpGroupNonUniformInverseBallot; break; - case glslang::EOpSubgroupBallotBitExtract: opCode = spv::OpGroupNonUniformBallotBitExtract; break; - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: opCode = spv::OpGroupNonUniformBallotBitCount; break; - case glslang::EOpSubgroupBallotFindLSB: opCode = spv::OpGroupNonUniformBallotFindLSB; break; - case glslang::EOpSubgroupBallotFindMSB: opCode = spv::OpGroupNonUniformBallotFindMSB; break; - case glslang::EOpSubgroupShuffle: opCode = spv::OpGroupNonUniformShuffle; break; - case glslang::EOpSubgroupShuffleXor: opCode = spv::OpGroupNonUniformShuffleXor; break; - case glslang::EOpSubgroupShuffleUp: opCode = spv::OpGroupNonUniformShuffleUp; break; - case glslang::EOpSubgroupShuffleDown: opCode = spv::OpGroupNonUniformShuffleDown; break; - case glslang::EOpSubgroupRotate: - case glslang::EOpSubgroupClusteredRotate: opCode = spv::OpGroupNonUniformRotateKHR; break; - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - if (isFloat) { - opCode = spv::OpGroupNonUniformFAdd; - } else { - opCode = spv::OpGroupNonUniformIAdd; - } - break; - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMul: - if (isFloat) { - opCode = spv::OpGroupNonUniformFMul; - } else { - opCode = spv::OpGroupNonUniformIMul; - } - break; - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMin: - if (isFloat) { - opCode = spv::OpGroupNonUniformFMin; - } else if (isUnsigned) { - opCode = spv::OpGroupNonUniformUMin; - } else { - opCode = spv::OpGroupNonUniformSMin; - } - break; - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveMax: - if (isFloat) { - opCode = spv::OpGroupNonUniformFMax; - } else if (isUnsigned) { - opCode = spv::OpGroupNonUniformUMax; - } else { - opCode = spv::OpGroupNonUniformSMax; - } - break; - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalAnd; - } else { - opCode = spv::OpGroupNonUniformBitwiseAnd; - } - break; - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveOr: - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalOr; - } else { - opCode = spv::OpGroupNonUniformBitwiseOr; - } - break; - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveXor: - case glslang::EOpSubgroupClusteredXor: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveXor: - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalXor; - } else { - opCode = spv::OpGroupNonUniformBitwiseXor; - } - break; - case glslang::EOpSubgroupQuadBroadcast: opCode = spv::OpGroupNonUniformQuadBroadcast; break; - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: opCode = spv::OpGroupNonUniformQuadSwap; break; - default: assert(0 && "Unhandled subgroup operation!"); - } - - // get the right Group Operation - spv::GroupOperation groupOperation = spv::GroupOperationMax; - switch (op) { - default: - break; - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - groupOperation = spv::GroupOperationReduce; - break; - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - groupOperation = spv::GroupOperationInclusiveScan; - break; - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - groupOperation = spv::GroupOperationExclusiveScan; - break; - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - groupOperation = spv::GroupOperationClusteredReduce; - break; - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - groupOperation = spv::GroupOperationPartitionedReduceNV; - break; - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - groupOperation = spv::GroupOperationPartitionedInclusiveScanNV; - break; - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - groupOperation = spv::GroupOperationPartitionedExclusiveScanNV; - break; - } - - // build the instruction - std::vector spvGroupOperands; - - // Every operation begins with the Execution Scope operand. - spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - // All other ops need the execution scope. Quad Control Ops don't need scope, it's always Quad. - if (opCode != spv::OpGroupNonUniformQuadAllKHR && opCode != spv::OpGroupNonUniformQuadAnyKHR) { - spvGroupOperands.push_back(executionScope); - } - - // Next, for all operations that use a Group Operation, push that as an operand. - if (groupOperation != spv::GroupOperationMax) { - spv::IdImmediate groupOperand = { false, (unsigned)groupOperation }; - spvGroupOperands.push_back(groupOperand); - } - - // Push back the operands next. - for (auto opIt = operands.cbegin(); opIt != operands.cend(); ++opIt) { - spv::IdImmediate operand = { true, *opIt }; - spvGroupOperands.push_back(operand); - } - - // Some opcodes have additional operands. - spv::Id directionId = spv::NoResult; - switch (op) { - default: break; - case glslang::EOpSubgroupQuadSwapHorizontal: directionId = builder.makeUintConstant(0); break; - case glslang::EOpSubgroupQuadSwapVertical: directionId = builder.makeUintConstant(1); break; - case glslang::EOpSubgroupQuadSwapDiagonal: directionId = builder.makeUintConstant(2); break; - } - if (directionId != spv::NoResult) { - spv::IdImmediate direction = { true, directionId }; - spvGroupOperands.push_back(direction); - } - - return builder.createOp(opCode, typeId, spvGroupOperands); -} - -spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, - spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - spv::Op opCode = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; - size_t consumedOperands = operands.size(); - spv::Id typeId0 = 0; - if (consumedOperands > 0) - typeId0 = builder.getTypeId(operands[0]); - spv::Id typeId1 = 0; - if (consumedOperands > 1) - typeId1 = builder.getTypeId(operands[1]); - spv::Id frexpIntType = 0; - - switch (op) { - case glslang::EOpMin: - if (isFloat) - libCall = nanMinMaxClamp ? spv::GLSLstd450NMin : spv::GLSLstd450FMin; - else if (isUnsigned) - libCall = spv::GLSLstd450UMin; - else - libCall = spv::GLSLstd450SMin; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpModf: - { - libCall = spv::GLSLstd450ModfStruct; - assert(builder.isFloatType(builder.getScalarTypeId(typeId0))); - int width = builder.getScalarTypeWidth(typeId0); - if (width == 16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - // The returned struct has two members of the same type as the first argument - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 1; - } - break; - case glslang::EOpMax: - if (isFloat) - libCall = nanMinMaxClamp ? spv::GLSLstd450NMax : spv::GLSLstd450FMax; - else if (isUnsigned) - libCall = spv::GLSLstd450UMax; - else - libCall = spv::GLSLstd450SMax; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpPow: - libCall = spv::GLSLstd450Pow; - break; - case glslang::EOpDot: - opCode = spv::OpDot; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan2; - break; - - case glslang::EOpClamp: - if (isFloat) - libCall = nanMinMaxClamp ? spv::GLSLstd450NClamp : spv::GLSLstd450FClamp; - else if (isUnsigned) - libCall = spv::GLSLstd450UClamp; - else - libCall = spv::GLSLstd450SClamp; - builder.promoteScalar(precision, operands.front(), operands[1]); - builder.promoteScalar(precision, operands.front(), operands[2]); - break; - case glslang::EOpMix: - if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) { - assert(isFloat); - libCall = spv::GLSLstd450FMix; - } else { - opCode = spv::OpSelect; - std::swap(operands.front(), operands.back()); - } - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpStep: - libCall = spv::GLSLstd450Step; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpSmoothStep: - libCall = spv::GLSLstd450SmoothStep; - builder.promoteScalar(precision, operands[0], operands[2]); - builder.promoteScalar(precision, operands[1], operands[2]); - break; - - case glslang::EOpDistance: - libCall = spv::GLSLstd450Distance; - break; - case glslang::EOpCross: - libCall = spv::GLSLstd450Cross; - break; - case glslang::EOpFaceForward: - libCall = spv::GLSLstd450FaceForward; - break; - case glslang::EOpReflect: - libCall = spv::GLSLstd450Reflect; - break; - case glslang::EOpRefract: - libCall = spv::GLSLstd450Refract; - break; - case glslang::EOpBarrier: - { - // This is for the extended controlBarrier function, with four operands. - // The unextended barrier() goes through createNoArgOperation. - assert(operands.size() == 4); - unsigned int executionScope = builder.getConstantScalar(operands[0]); - unsigned int memoryScope = builder.getConstantScalar(operands[1]); - unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]); - builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, - (spv::MemorySemanticsMask)semantics); - if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | - spv::MemorySemanticsMakeVisibleKHRMask | - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsVolatileMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || - memoryScope == spv::ScopeDevice)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - return 0; - } - break; - case glslang::EOpMemoryBarrier: - { - // This is for the extended memoryBarrier function, with three operands. - // The unextended memoryBarrier() goes through createNoArgOperation. - assert(operands.size() == 3); - unsigned int memoryScope = builder.getConstantScalar(operands[0]); - unsigned int semantics = builder.getConstantScalar(operands[1]) | builder.getConstantScalar(operands[2]); - builder.createMemoryBarrier((spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); - if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | - spv::MemorySemanticsMakeVisibleKHRMask | - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsVolatileMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - if (glslangIntermediate->usingVulkanMemoryModel() && memoryScope == spv::ScopeDevice) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - return 0; - } - break; - - case glslang::EOpInterpolateAtSample: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - libCall = spv::GLSLstd450InterpolateAtSample; - break; - case glslang::EOpInterpolateAtOffset: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - libCall = spv::GLSLstd450InterpolateAtOffset; - break; - case glslang::EOpAddCarry: - opCode = spv::OpIAddCarry; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpSubBorrow: - opCode = spv::OpISubBorrow; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpUMulExtended: - opCode = spv::OpUMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpIMulExtended: - opCode = spv::OpSMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpBitfieldExtract: - if (isUnsigned) - opCode = spv::OpBitFieldUExtract; - else - opCode = spv::OpBitFieldSExtract; - break; - case glslang::EOpBitfieldInsert: - opCode = spv::OpBitFieldInsert; - break; - - case glslang::EOpFma: - libCall = spv::GLSLstd450Fma; - break; - case glslang::EOpFrexp: - { - libCall = spv::GLSLstd450FrexpStruct; - assert(builder.isPointerType(typeId1)); - typeId1 = builder.getContainedTypeId(typeId1); - int width = builder.getScalarTypeWidth(typeId1); - if (width == 16) - // Using 16-bit exp operand, enable extension SPV_AMD_gpu_shader_int16 - builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); - if (builder.getNumComponents(operands[0]) == 1) - frexpIntType = builder.makeIntegerType(width, true); - else - frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), - builder.getNumComponents(operands[0])); - typeId = builder.makeStructResultType(typeId0, frexpIntType); - consumedOperands = 1; - } - break; - case glslang::EOpLdexp: - libCall = spv::GLSLstd450Ldexp; - break; - - case glslang::EOpReadInvocation: - return createInvocationsOperation(op, typeId, operands, typeProxy); - - case glslang::EOpSubgroupBroadcast: - case glslang::EOpSubgroupBallotBitExtract: - case glslang::EOpSubgroupShuffle: - case glslang::EOpSubgroupShuffleXor: - case glslang::EOpSubgroupShuffleUp: - case glslang::EOpSubgroupShuffleDown: - case glslang::EOpSubgroupRotate: - case glslang::EOpSubgroupClusteredRotate: - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - case glslang::EOpSubgroupQuadBroadcast: - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - return createSubgroupOperation(op, typeId, operands, typeProxy); - - case glslang::EOpSwizzleInvocations: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsAMD; - break; - case glslang::EOpSwizzleInvocationsMasked: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsMaskedAMD; - break; - case glslang::EOpWriteInvocation: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::WriteInvocationAMD; - break; - - case glslang::EOpMin3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMin3AMD; - else { - if (isUnsigned) - libCall = spv::UMin3AMD; - else - libCall = spv::SMin3AMD; - } - break; - case glslang::EOpMax3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMax3AMD; - else { - if (isUnsigned) - libCall = spv::UMax3AMD; - else - libCall = spv::SMax3AMD; - } - break; - case glslang::EOpMid3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMid3AMD; - else { - if (isUnsigned) - libCall = spv::UMid3AMD; - else - libCall = spv::SMid3AMD; - } - break; - - case glslang::EOpInterpolateAtVertex: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - libCall = spv::InterpolateAtVertexAMD; - break; - - case glslang::EOpReportIntersection: - typeId = builder.makeBoolType(); - opCode = spv::OpReportIntersectionKHR; - break; - case glslang::EOpTraceNV: - builder.createNoResultOp(spv::OpTraceNV, operands); - return 0; - case glslang::EOpTraceRayMotionNV: - builder.addExtension(spv::E_SPV_NV_ray_tracing_motion_blur); - builder.addCapability(spv::CapabilityRayTracingMotionBlurNV); - builder.createNoResultOp(spv::OpTraceRayMotionNV, operands); - return 0; - case glslang::EOpTraceKHR: - builder.createNoResultOp(spv::OpTraceRayKHR, operands); - return 0; - case glslang::EOpExecuteCallableNV: - builder.createNoResultOp(spv::OpExecuteCallableNV, operands); - return 0; - case glslang::EOpExecuteCallableKHR: - builder.createNoResultOp(spv::OpExecuteCallableKHR, operands); - return 0; - - case glslang::EOpRayQueryInitialize: - builder.createNoResultOp(spv::OpRayQueryInitializeKHR, operands); - return 0; - case glslang::EOpRayQueryTerminate: - builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operands); - return 0; - case glslang::EOpRayQueryGenerateIntersection: - builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR, operands); - return 0; - case glslang::EOpRayQueryConfirmIntersection: - builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operands); - return 0; - case glslang::EOpRayQueryProceed: - typeId = builder.makeBoolType(); - opCode = spv::OpRayQueryProceedKHR; - break; - case glslang::EOpRayQueryGetIntersectionType: - typeId = builder.makeUintType(32); - opCode = spv::OpRayQueryGetIntersectionTypeKHR; - break; - case glslang::EOpRayQueryGetRayTMin: - typeId = builder.makeFloatType(32); - opCode = spv::OpRayQueryGetRayTMinKHR; - break; - case glslang::EOpRayQueryGetRayFlags: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetRayFlagsKHR; - break; - case glslang::EOpRayQueryGetIntersectionT: - typeId = builder.makeFloatType(32); - opCode = spv::OpRayQueryGetIntersectionTKHR; - break; - case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionInstanceCustomIndexKHR; - break; - case glslang::EOpRayQueryGetIntersectionInstanceId: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR; - break; - case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: - typeId = builder.makeUintType(32); - opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR; - break; - case glslang::EOpRayQueryGetIntersectionGeometryIndex: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionGeometryIndexKHR; - break; - case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionPrimitiveIndexKHR; - break; - case glslang::EOpRayQueryGetIntersectionBarycentrics: - typeId = builder.makeVectorType(builder.makeFloatType(32), 2); - opCode = spv::OpRayQueryGetIntersectionBarycentricsKHR; - break; - case glslang::EOpRayQueryGetIntersectionFrontFace: - typeId = builder.makeBoolType(); - opCode = spv::OpRayQueryGetIntersectionFrontFaceKHR; - break; - case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: - typeId = builder.makeBoolType(); - opCode = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; - break; - case glslang::EOpRayQueryGetIntersectionObjectRayDirection: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetIntersectionObjectRayDirectionKHR; - break; - case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetIntersectionObjectRayOriginKHR; - break; - case glslang::EOpRayQueryGetWorldRayDirection: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetWorldRayDirectionKHR; - break; - case glslang::EOpRayQueryGetWorldRayOrigin: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetWorldRayOriginKHR; - break; - case glslang::EOpRayQueryGetIntersectionObjectToWorld: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpRayQueryGetIntersectionObjectToWorldKHR; - break; - case glslang::EOpRayQueryGetIntersectionWorldToObject: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpRayQueryGetIntersectionWorldToObjectKHR; - break; - case glslang::EOpWritePackedPrimitiveIndices4x8NV: - builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands); - return 0; - case glslang::EOpEmitMeshTasksEXT: - if (taskPayloadID) - operands.push_back(taskPayloadID); - // As per SPV_EXT_mesh_shader make it a terminating instruction in the current block - builder.makeStatementTerminator(spv::OpEmitMeshTasksEXT, operands, "post-OpEmitMeshTasksEXT"); - return 0; - case glslang::EOpSetMeshOutputsEXT: - builder.createNoResultOp(spv::OpSetMeshOutputsEXT, operands); - return 0; - case glslang::EOpCooperativeMatrixMulAddNV: - opCode = spv::OpCooperativeMatrixMulAddNV; - break; - case glslang::EOpHitObjectTraceRayNV: - builder.createNoResultOp(spv::OpHitObjectTraceRayNV, operands); - return 0; - case glslang::EOpHitObjectTraceRayMotionNV: - builder.createNoResultOp(spv::OpHitObjectTraceRayMotionNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitMotionNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitMotionNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitWithIndexNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitWithIndexNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitWithIndexMotionNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitWithIndexMotionNV, operands); - return 0; - case glslang::EOpHitObjectRecordMissNV: - builder.createNoResultOp(spv::OpHitObjectRecordMissNV, operands); - return 0; - case glslang::EOpHitObjectRecordMissMotionNV: - builder.createNoResultOp(spv::OpHitObjectRecordMissMotionNV, operands); - return 0; - case glslang::EOpHitObjectExecuteShaderNV: - builder.createNoResultOp(spv::OpHitObjectExecuteShaderNV, operands); - return 0; - case glslang::EOpHitObjectIsEmptyNV: - typeId = builder.makeBoolType(); - opCode = spv::OpHitObjectIsEmptyNV; - break; - case glslang::EOpHitObjectIsMissNV: - typeId = builder.makeBoolType(); - opCode = spv::OpHitObjectIsMissNV; - break; - case glslang::EOpHitObjectIsHitNV: - typeId = builder.makeBoolType(); - opCode = spv::OpHitObjectIsHitNV; - break; - case glslang::EOpHitObjectGetRayTMinNV: - typeId = builder.makeFloatType(32); - opCode = spv::OpHitObjectGetRayTMinNV; - break; - case glslang::EOpHitObjectGetRayTMaxNV: - typeId = builder.makeFloatType(32); - opCode = spv::OpHitObjectGetRayTMaxNV; - break; - case glslang::EOpHitObjectGetObjectRayOriginNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetObjectRayOriginNV; - break; - case glslang::EOpHitObjectGetObjectRayDirectionNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetObjectRayDirectionNV; - break; - case glslang::EOpHitObjectGetWorldRayOriginNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetWorldRayOriginNV; - break; - case glslang::EOpHitObjectGetWorldRayDirectionNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetWorldRayDirectionNV; - break; - case glslang::EOpHitObjectGetWorldToObjectNV: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpHitObjectGetWorldToObjectNV; - break; - case glslang::EOpHitObjectGetObjectToWorldNV: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpHitObjectGetObjectToWorldNV; - break; - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetInstanceCustomIndexNV; - break; - case glslang::EOpHitObjectGetInstanceIdNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetInstanceIdNV; - break; - case glslang::EOpHitObjectGetGeometryIndexNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetGeometryIndexNV; - break; - case glslang::EOpHitObjectGetPrimitiveIndexNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetPrimitiveIndexNV; - break; - case glslang::EOpHitObjectGetHitKindNV: - typeId = builder.makeIntegerType(32, 0); - opCode = spv::OpHitObjectGetHitKindNV; - break; - case glslang::EOpHitObjectGetCurrentTimeNV: - typeId = builder.makeFloatType(32); - opCode = spv::OpHitObjectGetCurrentTimeNV; - break; - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - typeId = builder.makeIntegerType(32, 0); - opCode = spv::OpHitObjectGetShaderBindingTableRecordIndexNV; - return 0; - case glslang::EOpHitObjectGetAttributesNV: - builder.createNoResultOp(spv::OpHitObjectGetAttributesNV, operands); - return 0; - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - typeId = builder.makeVectorType(builder.makeUintType(32), 2); - opCode = spv::OpHitObjectGetShaderRecordBufferHandleNV; - break; - case glslang::EOpReorderThreadNV: { - if (operands.size() == 2) { - builder.createNoResultOp(spv::OpReorderThreadWithHintNV, operands); - } else { - builder.createNoResultOp(spv::OpReorderThreadWithHitObjectNV, operands); - } - return 0; - - } - - case glslang::EOpImageSampleWeightedQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageSampleWeightedQCOM; - addImageProcessingQCOMDecoration(operands[2], spv::DecorationWeightTextureQCOM); - break; - case glslang::EOpImageBoxFilterQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBoxFilterQCOM; - break; - case glslang::EOpImageBlockMatchSADQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchSADQCOM; - addImageProcessingQCOMDecoration(operands[0], spv::DecorationBlockMatchTextureQCOM); - addImageProcessingQCOMDecoration(operands[2], spv::DecorationBlockMatchTextureQCOM); - break; - case glslang::EOpImageBlockMatchSSDQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchSSDQCOM; - addImageProcessingQCOMDecoration(operands[0], spv::DecorationBlockMatchTextureQCOM); - addImageProcessingQCOMDecoration(operands[2], spv::DecorationBlockMatchTextureQCOM); - break; - - case glslang::EOpFetchMicroTriangleVertexBarycentricNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 2); - opCode = spv::OpFetchMicroTriangleVertexBarycentricNV; - break; - - case glslang::EOpFetchMicroTriangleVertexPositionNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpFetchMicroTriangleVertexPositionNV; - break; - - case glslang::EOpImageBlockMatchWindowSSDQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchWindowSSDQCOM; - addImageProcessing2QCOMDecoration(operands[0], false); - addImageProcessing2QCOMDecoration(operands[2], false); - break; - case glslang::EOpImageBlockMatchWindowSADQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchWindowSADQCOM; - addImageProcessing2QCOMDecoration(operands[0], false); - addImageProcessing2QCOMDecoration(operands[2], false); - break; - case glslang::EOpImageBlockMatchGatherSSDQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchGatherSSDQCOM; - addImageProcessing2QCOMDecoration(operands[0], true); - addImageProcessing2QCOMDecoration(operands[2], true); - break; - case glslang::EOpImageBlockMatchGatherSADQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchGatherSADQCOM; - addImageProcessing2QCOMDecoration(operands[0], true); - addImageProcessing2QCOMDecoration(operands[2], true); - break; - case glslang::EOpCreateTensorLayoutNV: - return builder.createOp(spv::OpCreateTensorLayoutNV, typeId, std::vector{}); - case glslang::EOpCreateTensorViewNV: - return builder.createOp(spv::OpCreateTensorViewNV, typeId, std::vector{}); - case glslang::EOpTensorLayoutSetBlockSizeNV: - opCode = spv::OpTensorLayoutSetBlockSizeNV; - break; - case glslang::EOpTensorLayoutSetDimensionNV: - opCode = spv::OpTensorLayoutSetDimensionNV; - break; - case glslang::EOpTensorLayoutSetStrideNV: - opCode = spv::OpTensorLayoutSetStrideNV; - break; - case glslang::EOpTensorLayoutSliceNV: - opCode = spv::OpTensorLayoutSliceNV; - break; - case glslang::EOpTensorLayoutSetClampValueNV: - opCode = spv::OpTensorLayoutSetClampValueNV; - break; - case glslang::EOpTensorViewSetDimensionNV: - opCode = spv::OpTensorViewSetDimensionNV; - break; - case glslang::EOpTensorViewSetStrideNV: - opCode = spv::OpTensorViewSetStrideNV; - break; - case glslang::EOpTensorViewSetClipNV: - opCode = spv::OpTensorViewSetClipNV; - break; - default: - return 0; - } - - spv::Id id = 0; - if (libCall >= 0) { - // Use an extended instruction from the standard library. - // Construct the call arguments, without modifying the original operands vector. - // We might need the remaining arguments, e.g. in the EOpFrexp case. - std::vector callArguments(operands.begin(), operands.begin() + consumedOperands); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, callArguments); - } else if (opCode == spv::OpDot && !isFloat) { - // int dot(int, int) - // NOTE: never called for scalar/vector1, this is turned into simple mul before this can be reached - const int componentCount = builder.getNumComponents(operands[0]); - spv::Id mulOp = builder.createBinOp(spv::OpIMul, builder.getTypeId(operands[0]), operands[0], operands[1]); - builder.setPrecision(mulOp, precision); - id = builder.createCompositeExtract(mulOp, typeId, 0); - for (int i = 1; i < componentCount; ++i) { - builder.setPrecision(id, precision); - id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(mulOp, typeId, i)); - } - } else { - switch (consumedOperands) { - case 0: - // should all be handled by visitAggregate and createNoArgOperation - assert(0); - return 0; - case 1: - // should all be handled by createUnaryOperation - assert(0); - return 0; - case 2: - id = builder.createBinOp(opCode, typeId, operands[0], operands[1]); - break; - default: - // anything 3 or over doesn't have l-value operands, so all should be consumed - assert(consumedOperands == operands.size()); - id = builder.createOp(opCode, typeId, operands); - break; - } - } - - // Decode the return types that were structures - switch (op) { - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - id = builder.createCompositeExtract(id, typeId0, 0); - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]); - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - break; - case glslang::EOpModf: - { - assert(operands.size() == 2); - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[1]); - id = builder.createCompositeExtract(id, typeId0, 0); - } - break; - case glslang::EOpFrexp: - { - assert(operands.size() == 2); - if (builder.isFloatType(builder.getScalarTypeId(typeId1))) { - // "exp" is floating-point type (from HLSL intrinsic) - spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1); - member1 = builder.createUnaryOp(spv::OpConvertSToF, typeId1, member1); - builder.createStore(member1, operands[1]); - } else - // "exp" is integer type (from GLSL built-in function) - builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]); - id = builder.createCompositeExtract(id, typeId0, 0); - } - break; - default: - break; - } - - return builder.setPrecision(id, precision); -} - -// Intrinsics with no arguments (or no return value, and no precision). -spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId) -{ - // GLSL memory barriers use queuefamily scope in new model, device scope in old model - spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? - spv::ScopeQueueFamilyKHR : spv::ScopeDevice; - - switch (op) { - case glslang::EOpBarrier: - if (glslangIntermediate->getStage() == EShLangTessControl) { - if (glslangIntermediate->usingVulkanMemoryModel()) { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsAcquireReleaseMask); - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } else { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeInvocation, spv::MemorySemanticsMaskNone); - } - } else { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - } - return 0; - case glslang::EOpMemoryBarrier: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierBuffer: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierShared: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpGroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierAtomicCounter: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAtomicCounterMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierImage: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpAllMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, - spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpSubgroupBarrier: - builder.createControlBarrier(spv::ScopeSubgroup, spv::ScopeSubgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierBuffer: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierImage: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierShared: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - - case glslang::EOpEmitVertex: - builder.createNoResultOp(spv::OpEmitVertex); - return 0; - case glslang::EOpEndPrimitive: - builder.createNoResultOp(spv::OpEndPrimitive); - return 0; - - case glslang::EOpSubgroupElect: { - std::vector operands; - return createSubgroupOperation(op, typeId, operands, glslang::EbtVoid); - } - case glslang::EOpTime: - { - std::vector args; // Dummy arguments - spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args); - return builder.setPrecision(id, precision); - } - case glslang::EOpIgnoreIntersectionNV: - builder.createNoResultOp(spv::OpIgnoreIntersectionNV); - return 0; - case glslang::EOpTerminateRayNV: - builder.createNoResultOp(spv::OpTerminateRayNV); - return 0; - case glslang::EOpRayQueryInitialize: - builder.createNoResultOp(spv::OpRayQueryInitializeKHR); - return 0; - case glslang::EOpRayQueryTerminate: - builder.createNoResultOp(spv::OpRayQueryTerminateKHR); - return 0; - case glslang::EOpRayQueryGenerateIntersection: - builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR); - return 0; - case glslang::EOpRayQueryConfirmIntersection: - builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR); - return 0; - case glslang::EOpBeginInvocationInterlock: - builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT); - return 0; - case glslang::EOpEndInvocationInterlock: - builder.createNoResultOp(spv::OpEndInvocationInterlockEXT); - return 0; - - case glslang::EOpIsHelperInvocation: - { - std::vector args; // Dummy arguments - builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation); - builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT); - return builder.createOp(spv::OpIsHelperInvocationEXT, typeId, args); - } - - case glslang::EOpReadClockSubgroupKHR: { - std::vector args; - args.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); - builder.addExtension(spv::E_SPV_KHR_shader_clock); - builder.addCapability(spv::CapabilityShaderClockKHR); - return builder.createOp(spv::OpReadClockKHR, typeId, args); - } - - case glslang::EOpReadClockDeviceKHR: { - std::vector args; - args.push_back(builder.makeUintConstant(spv::ScopeDevice)); - builder.addExtension(spv::E_SPV_KHR_shader_clock); - builder.addCapability(spv::CapabilityShaderClockKHR); - return builder.createOp(spv::OpReadClockKHR, typeId, args); - } - case glslang::EOpStencilAttachmentReadEXT: - case glslang::EOpDepthAttachmentReadEXT: - { - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - - spv::Decoration precision; - spv::Op spv_op; - if (op == glslang::EOpStencilAttachmentReadEXT) - { - precision = spv::DecorationRelaxedPrecision; - spv_op = spv::OpStencilAttachmentReadEXT; - builder.addCapability(spv::CapabilityTileImageStencilReadAccessEXT); - } - else - { - precision = spv::NoPrecision; - spv_op = spv::OpDepthAttachmentReadEXT; - builder.addCapability(spv::CapabilityTileImageDepthReadAccessEXT); - } - - std::vector args; // Dummy args - spv::Id result = builder.createOp(spv_op, typeId, args); - return builder.setPrecision(result, precision); - } - default: - break; - } - - logger->missingFunctionality("unknown operation with no arguments"); - - return 0; -} - -spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol) -{ - auto iter = symbolValues.find(symbol->getId()); - spv::Id id; - if (symbolValues.end() != iter) { - id = iter->second; - return id; - } - - // it was not found, create it - spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); - auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType()); - - // There are pairs of symbols that map to the same SPIR-V built-in: - // gl_ObjectToWorldEXT and gl_ObjectToWorld3x4EXT, and gl_WorldToObjectEXT - // and gl_WorldToObject3x4EXT. SPIR-V forbids having two OpVariables - // with the same BuiltIn in the same storage class, so we must re-use one. - const bool mayNeedToReuseBuiltIn = - builtIn == spv::BuiltInObjectToWorldKHR || - builtIn == spv::BuiltInWorldToObjectKHR; - - if (mayNeedToReuseBuiltIn) { - auto iter = builtInVariableIds.find(uint32_t(builtIn)); - if (builtInVariableIds.end() != iter) { - id = iter->second; - symbolValues[symbol->getId()] = id; - if (forcedType.second != spv::NoType) - forceType[id] = forcedType.second; - return id; - } - } - - if (symbol->getBasicType() == glslang::EbtFunction) { - return 0; - } - - id = createSpvVariable(symbol, forcedType.first); - - if (mayNeedToReuseBuiltIn) { - builtInVariableIds.insert({uint32_t(builtIn), id}); - } - - symbolValues[symbol->getId()] = id; - if (forcedType.second != spv::NoType) - forceType[id] = forcedType.second; - - if (symbol->getBasicType() != glslang::EbtBlock) { - builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType())); - builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier())); - builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier())); - addMeshNVDecoration(id, /*member*/ -1, symbol->getType().getQualifier()); - if (symbol->getQualifier().hasComponent()) - builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent); - if (symbol->getQualifier().hasIndex()) - builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex); - if (symbol->getType().getQualifier().hasSpecConstantId()) - builder.addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId); - // atomic counters use this: - if (symbol->getQualifier().hasOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset); - } - - if (symbol->getQualifier().hasLocation()) { - if (!(glslangIntermediate->isRayTracingStage() && - (glslangIntermediate->IsRequestedExtension(glslang::E_GL_EXT_ray_tracing) || - glslangIntermediate->IsRequestedExtension(glslang::E_GL_NV_shader_invocation_reorder)) - && (builder.getStorageClass(id) == spv::StorageClassRayPayloadKHR || - builder.getStorageClass(id) == spv::StorageClassIncomingRayPayloadKHR || - builder.getStorageClass(id) == spv::StorageClassCallableDataKHR || - builder.getStorageClass(id) == spv::StorageClassIncomingCallableDataKHR || - builder.getStorageClass(id) == spv::StorageClassHitObjectAttributeNV))) { - // Location values are used to link TraceRayKHR/ExecuteCallableKHR/HitObjectGetAttributesNV - // to corresponding variables but are not valid in SPIRV since they are supported only - // for Input/Output Storage classes. - builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation); - } - } - - builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier())); - if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { - builder.addCapability(spv::CapabilityGeometryStreams); - builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream); - } - if (symbol->getQualifier().hasSet()) - builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet); - else if (IsDescriptorResource(symbol->getType())) { - // default to 0 - builder.addDecoration(id, spv::DecorationDescriptorSet, 0); - } - if (symbol->getQualifier().hasBinding()) - builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding); - else if (IsDescriptorResource(symbol->getType())) { - // default to 0 - builder.addDecoration(id, spv::DecorationBinding, 0); - } - if (symbol->getQualifier().hasAttachment()) - builder.addDecoration(id, spv::DecorationInputAttachmentIndex, symbol->getQualifier().layoutAttachment); - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - if (symbol->getQualifier().hasXfbBuffer()) { - builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer); - unsigned stride = glslangIntermediate->getXfbStride(symbol->getQualifier().layoutXfbBuffer); - if (stride != glslang::TQualifier::layoutXfbStrideEnd) - builder.addDecoration(id, spv::DecorationXfbStride, stride); - } - if (symbol->getQualifier().hasXfbOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset); - } - - // add built-in variable decoration - if (builtIn != spv::BuiltInMax) { - // WorkgroupSize deprecated in spirv1.6 - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6 || - builtIn != spv::BuiltInWorkgroupSize) - builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); - } - - // Add volatile decoration to HelperInvocation for spirv1.6 and beyond - if (builtIn == spv::BuiltInHelperInvocation && - !glslangIntermediate->usingVulkanMemoryModel() && - glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - builder.addDecoration(id, spv::DecorationVolatile); - } - - // Subgroup builtins which have input storage class are volatile for ray tracing stages. - if (symbol->getType().isImage() || symbol->getQualifier().isPipeInput()) { - std::vector memory; - TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, - glslangIntermediate->usingVulkanMemoryModel()); - for (unsigned int i = 0; i < memory.size(); ++i) - builder.addDecoration(id, memory[i]); - } - - if (builtIn == spv::BuiltInSampleMask) { - spv::Decoration decoration; - // GL_NV_sample_mask_override_coverage extension - if (glslangIntermediate->getLayoutOverrideCoverage()) - decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV; - else - decoration = (spv::Decoration)spv::DecorationMax; - builder.addDecoration(id, decoration); - if (decoration != spv::DecorationMax) { - builder.addCapability(spv::CapabilitySampleMaskOverrideCoverageNV); - builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage); - } - } - else if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (symbol->getQualifier().layoutViewportRelative) { - builder.addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048) { - builder.addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, - symbol->getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - - if (symbol->getQualifier().layoutPassthrough) { - builder.addDecoration(id, spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } - if (symbol->getQualifier().pervertexNV) { - builder.addDecoration(id, spv::DecorationPerVertexNV); - builder.addCapability(spv::CapabilityFragmentBarycentricNV); - builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); - } - - if (symbol->getQualifier().pervertexEXT) { - builder.addDecoration(id, spv::DecorationPerVertexKHR); - builder.addCapability(spv::CapabilityFragmentBarycentricKHR); - builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); - } - - if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, - symbol->getType().getQualifier().semanticName); - } - - if (symbol->isReference()) { - builder.addDecoration(id, symbol->getType().getQualifier().restrict ? - spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); - } - - // Add SPIR-V decorations (GL_EXT_spirv_intrinsics) - if (symbol->getType().getQualifier().hasSpirvDecorate()) - applySpirvDecorate(symbol->getType(), id, {}); - - return id; -} - -// add per-primitive, per-view. per-task decorations to a struct member (member >= 0) or an object -void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier) -{ - bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) != - glslangIntermediate->getRequestedExtensions().end()); - - if (member >= 0) { - if (qualifier.perPrimitiveNV) { - // Need to add capability/extension for fragment shader. - // Mesh shader already adds this by default. - if (glslangIntermediate->getStage() == EShLangFragment) { - if(isMeshShaderExt) { - builder.addCapability(spv::CapabilityMeshShadingEXT); - builder.addExtension(spv::E_SPV_EXT_mesh_shader); - } else { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); - } - } - builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerPrimitiveNV); - } - if (qualifier.perViewNV) - builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerViewNV); - if (qualifier.perTaskNV) - builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerTaskNV); - } else { - if (qualifier.perPrimitiveNV) { - // Need to add capability/extension for fragment shader. - // Mesh shader already adds this by default. - if (glslangIntermediate->getStage() == EShLangFragment) { - if(isMeshShaderExt) { - builder.addCapability(spv::CapabilityMeshShadingEXT); - builder.addExtension(spv::E_SPV_EXT_mesh_shader); - } else { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); - } - } - builder.addDecoration(id, spv::DecorationPerPrimitiveNV); - } - if (qualifier.perViewNV) - builder.addDecoration(id, spv::DecorationPerViewNV); - if (qualifier.perTaskNV) - builder.addDecoration(id, spv::DecorationPerTaskNV); - } -} - -bool TGlslangToSpvTraverser::hasQCOMImageProceessingDecoration(spv::Id id, spv::Decoration decor) -{ - std::vector &decoVec = idToQCOMDecorations[id]; - for ( auto d : decoVec ) { - if ( d == decor ) - return true; - } - return false; -} - -void TGlslangToSpvTraverser::addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor) -{ - spv::Op opc = builder.getOpCode(id); - if (opc == spv::OpSampledImage) { - id = builder.getIdOperand(id, 0); - opc = builder.getOpCode(id); - } - - if (opc == spv::OpLoad) { - spv::Id texid = builder.getIdOperand(id, 0); - if (!hasQCOMImageProceessingDecoration(texid, decor)) {// - builder.addDecoration(texid, decor); - idToQCOMDecorations[texid].push_back(decor); - } - } -} - -void TGlslangToSpvTraverser::addImageProcessing2QCOMDecoration(spv::Id id, bool isForGather) -{ - if (isForGather) { - return addImageProcessingQCOMDecoration(id, spv::DecorationBlockMatchTextureQCOM); - } - - auto addDecor = - [this](spv::Id id, spv::Decoration decor) { - spv::Id tsopc = this->builder.getOpCode(id); - if (tsopc == spv::OpLoad) { - spv::Id tsid = this->builder.getIdOperand(id, 0); - if (this->glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { - assert(iOSet.count(tsid) > 0); - } - if (!hasQCOMImageProceessingDecoration(tsid, decor)) { - this->builder.addDecoration(tsid, decor); - idToQCOMDecorations[tsid].push_back(decor); - } - } - }; - - spv::Id opc = builder.getOpCode(id); - bool isInterfaceObject = (opc != spv::OpSampledImage); - - if (!isInterfaceObject) { - addDecor(builder.getIdOperand(id, 0), spv::DecorationBlockMatchTextureQCOM); - addDecor(builder.getIdOperand(id, 1), spv::DecorationBlockMatchSamplerQCOM); - } else { - addDecor(id, spv::DecorationBlockMatchTextureQCOM); - addDecor(id, spv::DecorationBlockMatchSamplerQCOM); - } -} - -// Make a full tree of instructions to build a SPIR-V specialization constant, -// or regular constant if possible. -// -// TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though -// -// Recursively walk the nodes. The nodes form a tree whose leaves are -// regular constants, which themselves are trees that createSpvConstant() -// recursively walks. So, this function walks the "top" of the tree: -// - emit specialization constant-building instructions for specConstant -// - when running into a non-spec-constant, switch to createSpvConstant() -spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node) -{ - assert(node.getQualifier().isConstant()); - - // Handle front-end constants first (non-specialization constants). - if (! node.getQualifier().specConstant) { - // hand off to the non-spec-constant path - assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); - int nextConst = 0; - return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? - node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), - nextConst, false); - } - - // We now know we have a specialization constant to build - - // Extra capabilities may be needed. - if (node.getType().contains8BitInt()) - builder.addCapability(spv::CapabilityInt8); - if (node.getType().contains16BitFloat()) - builder.addCapability(spv::CapabilityFloat16); - if (node.getType().contains16BitInt()) - builder.addCapability(spv::CapabilityInt16); - if (node.getType().contains64BitInt()) - builder.addCapability(spv::CapabilityInt64); - if (node.getType().containsDouble()) - builder.addCapability(spv::CapabilityFloat64); - - // gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants, - // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ... - if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); - } - } - return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); - } - - // An AST node labelled as specialization constant should be a symbol node. - // Its initializer should either be a sub tree with constant nodes, or a constant union array. - if (auto* sn = node.getAsSymbolNode()) { - spv::Id result; - if (auto* sub_tree = sn->getConstSubtree()) { - // Traverse the constant constructor sub tree like generating normal run-time instructions. - // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard - // will set the builder into spec constant op instruction generating mode. - sub_tree->traverse(this); - result = accessChainLoad(sub_tree->getType()); - } else if (auto* const_union_array = &sn->getConstArray()) { - int nextConst = 0; - result = createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true); - } else { - logger->missingFunctionality("Invalid initializer for spec onstant."); - return spv::NoResult; - } - builder.addName(result, sn->getName().c_str()); - return result; - } - - // Neither a front-end constant node, nor a specialization constant node with constant union array or - // constant sub tree as initializer. - logger->missingFunctionality("Neither a front-end constant nor a spec constant."); - return spv::NoResult; -} - -// Use 'consts' as the flattened glslang source of scalar constants to recursively -// build the aggregate SPIR-V constant. -// -// If there are not enough elements present in 'consts', 0 will be substituted; -// an empty 'consts' can be used to create a fully zeroed SPIR-V constant. -// -spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, - const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) -{ - // vector of constants for SPIR-V - std::vector spvConsts; - - // Type is used for struct and array constants - spv::Id typeId = convertGlslangToSpvType(glslangType); - - if (glslangType.isArray()) { - glslang::TType elementType(glslangType, 0); - for (int i = 0; i < glslangType.getOuterArraySize(); ++i) - spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false)); - } else if (glslangType.isMatrix()) { - glslang::TType vectorType(glslangType, 0); - for (int col = 0; col < glslangType.getMatrixCols(); ++col) - spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false)); - } else if (glslangType.isCoopMat()) { - glslang::TType componentType(glslangType.getBasicType()); - spvConsts.push_back(createSpvConstantFromConstUnionArray(componentType, consts, nextConst, false)); - } else if (glslangType.isStruct()) { - glslang::TVector::const_iterator iter; - for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) - spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); - } else if (glslangType.getVectorSize() > 1) { - for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { - bool zero = nextConst >= consts.size(); - switch (glslangType.getBasicType()) { - case glslang::EbtInt: - spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst())); - break; - case glslang::EbtUint: - spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst())); - break; - case glslang::EbtFloat: - spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; - case glslang::EbtBool: - spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst())); - break; - case glslang::EbtInt8: - builder.addCapability(spv::CapabilityInt8); - spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const())); - break; - case glslang::EbtUint8: - builder.addCapability(spv::CapabilityInt8); - spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const())); - break; - case glslang::EbtInt16: - builder.addCapability(spv::CapabilityInt16); - spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const())); - break; - case glslang::EbtUint16: - builder.addCapability(spv::CapabilityInt16); - spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const())); - break; - case glslang::EbtInt64: - spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const())); - break; - case glslang::EbtUint64: - spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const())); - break; - case glslang::EbtDouble: - spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst())); - break; - case glslang::EbtFloat16: - builder.addCapability(spv::CapabilityFloat16); - spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; - default: - assert(0); - break; - } - ++nextConst; - } - } else { - // we have a non-aggregate (scalar) constant - bool zero = nextConst >= consts.size(); - spv::Id scalar = 0; - switch (glslangType.getBasicType()) { - case glslang::EbtInt: - scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant); - break; - case glslang::EbtUint: - scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant); - break; - case glslang::EbtFloat: - scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtBool: - scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant); - break; - case glslang::EbtInt8: - builder.addCapability(spv::CapabilityInt8); - scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant); - break; - case glslang::EbtUint8: - builder.addCapability(spv::CapabilityInt8); - scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant); - break; - case glslang::EbtInt16: - builder.addCapability(spv::CapabilityInt16); - scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant); - break; - case glslang::EbtUint16: - builder.addCapability(spv::CapabilityInt16); - scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant); - break; - case glslang::EbtInt64: - scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant); - break; - case glslang::EbtUint64: - scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); - break; - case glslang::EbtDouble: - scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtFloat16: - builder.addCapability(spv::CapabilityFloat16); - scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtReference: - scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); - scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar); - break; - case glslang::EbtString: - scalar = builder.getStringId(consts[nextConst].getSConst()->c_str()); - break; - default: - assert(0); - break; - } - ++nextConst; - return scalar; - } - - return builder.makeCompositeConstant(typeId, spvConsts); -} - -// Return true if the node is a constant or symbol whose reading has no -// non-trivial observable cost or effect. -bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) -{ - // don't know what this is - if (node == nullptr) - return false; - - // a constant is safe - if (node->getAsConstantUnion() != nullptr) - return true; - - // not a symbol means non-trivial - if (node->getAsSymbolNode() == nullptr) - return false; - - // a symbol, depends on what's being read - switch (node->getType().getQualifier().storage) { - case glslang::EvqTemporary: - case glslang::EvqGlobal: - case glslang::EvqIn: - case glslang::EvqInOut: - case glslang::EvqConst: - case glslang::EvqConstReadOnly: - case glslang::EvqUniform: - return true; - default: - return false; - } -} - -// A node is trivial if it is a single operation with no side effects. -// HLSL (and/or vectors) are always trivial, as it does not short circuit. -// Otherwise, error on the side of saying non-trivial. -// Return true if trivial. -bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node) -{ - if (node == nullptr) - return false; - - // count non scalars as trivial, as well as anything coming from HLSL - if (! node->getType().isScalarOrVec1() || glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return true; - - // symbols and constants are trivial - if (isTrivialLeaf(node)) - return true; - - // otherwise, it needs to be a simple operation or one or two leaf nodes - - // not a simple operation - const glslang::TIntermBinary* binaryNode = node->getAsBinaryNode(); - const glslang::TIntermUnary* unaryNode = node->getAsUnaryNode(); - if (binaryNode == nullptr && unaryNode == nullptr) - return false; - - // not on leaf nodes - if (binaryNode && (! isTrivialLeaf(binaryNode->getLeft()) || ! isTrivialLeaf(binaryNode->getRight()))) - return false; - - if (unaryNode && ! isTrivialLeaf(unaryNode->getOperand())) { - return false; - } - - if (IsOpNumericConv(node->getAsOperator()->getOp()) && - node->getType().getBasicType() == glslang::EbtBool) { - return true; - } - - switch (node->getAsOperator()->getOp()) { - case glslang::EOpLogicalNot: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - case glslang::EOpLogicalXor: - case glslang::EOpAny: - case glslang::EOpAll: - return true; - default: - return false; - } -} - -// Emit short-circuiting code, where 'right' is never evaluated unless -// the left side is true (for &&) or false (for ||). -spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, - glslang::TIntermTyped& right) -{ - spv::Id boolTypeId = builder.makeBoolType(); - - // emit left operand - builder.clearAccessChain(); - left.traverse(this); - spv::Id leftId = accessChainLoad(left.getType()); - - // Operands to accumulate OpPhi operands - std::vector phiOperands; - phiOperands.reserve(4); - // accumulate left operand's phi information - phiOperands.push_back(leftId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // Make the two kinds of operation symmetric with a "!" - // || => emit "if (! left) result = right" - // && => emit "if ( left) result = right" - // - // TODO: this runtime "not" for || could be avoided by adding functionality - // to 'builder' to have an "else" without an "then" - if (op == glslang::EOpLogicalOr) - leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId); - - // make an "if" based on the left value - spv::Builder::If ifBuilder(leftId, spv::SelectionControlMaskNone, builder); - - // emit right operand as the "then" part of the "if" - builder.clearAccessChain(); - right.traverse(this); - spv::Id rightId = accessChainLoad(right.getType()); - - // accumulate left operand's phi information - phiOperands.push_back(rightId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // finish the "if" - ifBuilder.makeEndIf(); - - // phi together the two results - return builder.createOp(spv::OpPhi, boolTypeId, phiOperands); -} - -// Return type Id of the imported set of extended instructions corresponds to the name. -// Import this set if it has not been imported yet. -spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name) -{ - if (extBuiltinMap.find(name) != extBuiltinMap.end()) - return extBuiltinMap[name]; - else { - spv::Id extBuiltins = builder.import(name); - extBuiltinMap[name] = extBuiltins; - return extBuiltins; - } -} - -} // end anonymous namespace - -namespace glslang { - -void GetSpirvVersion(std::string& version) -{ - const int bufSize = 100; - char buf[bufSize]; - snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision); - version = buf; -} - -// For low-order part of the generator's magic number. Bump up -// when there is a change in the style (e.g., if SSA form changes, -// or a different instruction sequence to do something gets used). -int GetSpirvGeneratorVersion() -{ - // return 1; // start - // return 2; // EOpAtomicCounterDecrement gets a post decrement, to map between GLSL -> SPIR-V - // return 3; // change/correct barrier-instruction operands, to match memory model group decisions - // return 4; // some deeper access chains: for dynamic vector component, and local Boolean component - // return 5; // make OpArrayLength result type be an int with signedness of 0 - // return 6; // revert version 5 change, which makes a different (new) kind of incorrect code, - // versions 4 and 6 each generate OpArrayLength as it has long been done - // return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent - // return 8; // switch to new dead block eliminator; use OpUnreachable - // return 9; // don't include opaque function parameters in OpEntryPoint global's operand list - // return 10; // Generate OpFUnordNotEqual for != comparisons - return 11; // Make OpEmitMeshTasksEXT a terminal instruction -} - -// Write SPIR-V out to a binary file -bool OutputSpvBin(const std::vector& spirv, const char* baseName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) { - printf("ERROR: Failed to open file: %s\n", baseName); - return false; - } - for (int i = 0; i < (int)spirv.size(); ++i) { - unsigned int word = spirv[i]; - out.write((const char*)&word, 4); - } - out.close(); - return true; -} - -// Write SPIR-V out to a text file with 32-bit hexadecimal words -bool OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) { - printf("ERROR: Failed to open file: %s\n", baseName); - return false; - } - out << "\t// " << - GetSpirvGeneratorVersion() << - GLSLANG_VERSION_MAJOR << "." << GLSLANG_VERSION_MINOR << "." << GLSLANG_VERSION_PATCH << - GLSLANG_VERSION_FLAVOR << std::endl; - if (varName != nullptr) { - out << "\t #pragma once" << std::endl; - out << "const uint32_t " << varName << "[] = {" << std::endl; - } - const int WORDS_PER_LINE = 8; - for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) { - out << "\t"; - for (int j = 0; j < WORDS_PER_LINE && i + j < (int)spirv.size(); ++j) { - const unsigned int word = spirv[i + j]; - out << "0x" << std::hex << std::setw(8) << std::setfill('0') << word; - if (i + j + 1 < (int)spirv.size()) { - out << ","; - } - } - out << std::endl; - } - if (varName != nullptr) { - out << "};"; - out << std::endl; - } - out.close(); - return true; -} - -// -// Set up the glslang traversal -// -void GlslangToSpv(const TIntermediate& intermediate, std::vector& spirv, SpvOptions* options) -{ - spv::SpvBuildLogger logger; - GlslangToSpv(intermediate, spirv, &logger, options); -} - -void GlslangToSpv(const TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, SpvOptions* options) -{ - TIntermNode* root = intermediate.getTreeRoot(); - - if (root == nullptr) - return; - - SpvOptions defaultOptions; - if (options == nullptr) - options = &defaultOptions; - - GetThreadPoolAllocator().push(); - - TGlslangToSpvTraverser it(intermediate.getSpv().spv, &intermediate, logger, *options); - root->traverse(&it); - it.finishSpv(options->compileOnly); - it.dumpSpv(spirv); - -#if ENABLE_OPT - // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan - // eg. forward and remove memory writes of opaque types. - bool prelegalization = intermediate.getSource() == EShSourceHlsl; - if ((prelegalization || options->optimizeSize) && !options->disableOptimizer) { - SpirvToolsTransform(intermediate, spirv, logger, options); - prelegalization = false; - } - else if (options->stripDebugInfo) { - // Strip debug info even if optimization is disabled. - SpirvToolsStripDebugInfo(intermediate, spirv, logger); - } - - if (options->validate) - SpirvToolsValidate(intermediate, spirv, logger, prelegalization); - - if (options->disassemble) - SpirvToolsDisassemble(std::cout, spirv); - -#endif - - GetThreadPoolAllocator().pop(); -} - -} // end namespace glslang diff --git a/include/SPIRV/GlslangToSpv.h b/include/SPIRV/GlslangToSpv.h deleted file mode 100644 index 3378c15f..00000000 --- a/include/SPIRV/GlslangToSpv.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (C) 2014 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include -#include - -#include "Logger.h" -#include "/Include/visibility.h" - -namespace glslang { -class TIntermediate; - -struct SpvOptions { - bool generateDebugInfo {false}; - bool stripDebugInfo {false}; - bool disableOptimizer {true}; - bool optimizeSize {false}; - bool disassemble {false}; - bool validate {false}; - bool emitNonSemanticShaderDebugInfo {false}; - bool emitNonSemanticShaderDebugSource{ false }; - bool compileOnly{false}; - bool optimizerAllowExpandedIDBound{false}; -}; - -GLSLANG_EXPORT void GetSpirvVersion(std::string&); -GLSLANG_EXPORT int GetSpirvGeneratorVersion(); -GLSLANG_EXPORT void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - SpvOptions* options = nullptr); -GLSLANG_EXPORT void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); -GLSLANG_EXPORT bool OutputSpvBin(const std::vector& spirv, const char* baseName); -GLSLANG_EXPORT bool OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); - -} diff --git a/include/SPIRV/InReadableOrder.cpp b/include/SPIRV/InReadableOrder.cpp deleted file mode 100644 index 9d9410be..00000000 --- a/include/SPIRV/InReadableOrder.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// The SPIR-V spec requires code blocks to appear in an order satisfying the -// dominator-tree direction (ie, dominator before the dominated). This is, -// actually, easy to achieve: any pre-order CFG traversal algorithm will do it. -// Because such algorithms visit a block only after traversing some path to it -// from the root, they necessarily visit the block's idom first. -// -// But not every graph-traversal algorithm outputs blocks in an order that -// appears logical to human readers. The problem is that unrelated branches may -// be interspersed with each other, and merge blocks may come before some of the -// branches being merged. -// -// A good, human-readable order of blocks may be achieved by performing -// depth-first search but delaying merge nodes until after all their branches -// have been visited. This is implemented below by the inReadableOrder() -// function. - -#include "spvIR.h" - -#include -#include - -using spv::Block; -using spv::Id; - -namespace { -// Traverses CFG in a readable order, invoking a pre-set callback on each block. -// Use by calling visit() on the root block. -class ReadableOrderTraverser { -public: - ReadableOrderTraverser(std::function callback) - : callback_(callback) {} - // Visits the block if it hasn't been visited already and isn't currently - // being delayed. Invokes callback(block, why, header), then descends into its - // successors. Delays merge-block and continue-block processing until all - // the branches have been completed. If |block| is an unreachable merge block or - // an unreachable continue target, then |header| is the corresponding header block. - void visit(Block* block, spv::ReachReason why, Block* header) - { - assert(block); - if (why == spv::ReachViaControlFlow) { - reachableViaControlFlow_.insert(block); - } - if (visited_.count(block) || delayed_.count(block)) - return; - callback_(block, why, header); - visited_.insert(block); - Block* mergeBlock = nullptr; - Block* continueBlock = nullptr; - auto mergeInst = block->getMergeInstruction(); - if (mergeInst) { - Id mergeId = mergeInst->getIdOperand(0); - mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock(); - delayed_.insert(mergeBlock); - if (mergeInst->getOpCode() == spv::OpLoopMerge) { - Id continueId = mergeInst->getIdOperand(1); - continueBlock = - block->getParent().getParent().getInstruction(continueId)->getBlock(); - delayed_.insert(continueBlock); - } - } - if (why == spv::ReachViaControlFlow) { - const auto& successors = block->getSuccessors(); - for (auto it = successors.cbegin(); it != successors.cend(); ++it) - visit(*it, why, nullptr); - } - if (continueBlock) { - const spv::ReachReason continueWhy = - (reachableViaControlFlow_.count(continueBlock) > 0) - ? spv::ReachViaControlFlow - : spv::ReachDeadContinue; - delayed_.erase(continueBlock); - visit(continueBlock, continueWhy, block); - } - if (mergeBlock) { - const spv::ReachReason mergeWhy = - (reachableViaControlFlow_.count(mergeBlock) > 0) - ? spv::ReachViaControlFlow - : spv::ReachDeadMerge; - delayed_.erase(mergeBlock); - visit(mergeBlock, mergeWhy, block); - } - } - -private: - std::function callback_; - // Whether a block has already been visited or is being delayed. - std::unordered_set visited_, delayed_; - - // The set of blocks that actually are reached via control flow. - std::unordered_set reachableViaControlFlow_; -}; -} - -void spv::inReadableOrder(Block* root, std::function callback) -{ - ReadableOrderTraverser(callback).visit(root, spv::ReachViaControlFlow, nullptr); -} diff --git a/include/SPIRV/Logger.cpp b/include/SPIRV/Logger.cpp deleted file mode 100644 index 48bd4e3a..00000000 --- a/include/SPIRV/Logger.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include "Logger.h" - -#include -#include -#include - -namespace spv { - -void SpvBuildLogger::tbdFunctionality(const std::string& f) -{ - if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures)) - tbdFeatures.push_back(f); -} - -void SpvBuildLogger::missingFunctionality(const std::string& f) -{ - if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures)) - missingFeatures.push_back(f); -} - -std::string SpvBuildLogger::getAllMessages() const { - std::ostringstream messages; - for (auto it = tbdFeatures.cbegin(); it != tbdFeatures.cend(); ++it) - messages << "TBD functionality: " << *it << "\n"; - for (auto it = missingFeatures.cbegin(); it != missingFeatures.cend(); ++it) - messages << "Missing functionality: " << *it << "\n"; - for (auto it = warnings.cbegin(); it != warnings.cend(); ++it) - messages << "warning: " << *it << "\n"; - for (auto it = errors.cbegin(); it != errors.cend(); ++it) - messages << "error: " << *it << "\n"; - return messages.str(); -} - -} // end spv namespace diff --git a/include/SPIRV/Logger.h b/include/SPIRV/Logger.h deleted file mode 100644 index d434d679..00000000 --- a/include/SPIRV/Logger.h +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_SPIRV_LOGGER_H -#define GLSLANG_SPIRV_LOGGER_H - -#include -#include -#include "/Include/visibility.h" - -namespace spv { - -// A class for holding all SPIR-V build status messages, including -// missing/TBD functionalities, warnings, and errors. -class GLSLANG_EXPORT SpvBuildLogger { -public: - SpvBuildLogger() {} - - // Registers a TBD functionality. - void tbdFunctionality(const std::string& f); - // Registers a missing functionality. - void missingFunctionality(const std::string& f); - - // Logs a warning. - void warning(const std::string& w) { warnings.push_back(w); } - // Logs an error. - void error(const std::string& e) { errors.push_back(e); } - - // Returns all messages accumulated in the order of: - // TBD functionalities, missing functionalities, warnings, errors. - std::string getAllMessages() const; - -private: - SpvBuildLogger(const SpvBuildLogger&); - - std::vector tbdFeatures; - std::vector missingFeatures; - std::vector warnings; - std::vector errors; -}; - -} // end spv namespace - -#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/include/SPIRV/NonSemanticDebugPrintf.h b/include/SPIRV/NonSemanticDebugPrintf.h deleted file mode 100644 index 3ca7247f..00000000 --- a/include/SPIRV/NonSemanticDebugPrintf.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2020 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and/or associated documentation files (the -// "Materials"), to deal in the Materials without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Materials, and to -// permit persons to whom the Materials are furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS -// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS -// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT -// https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -// - -#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ -#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - NonSemanticDebugPrintfRevision = 1, - NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff -}; - -enum NonSemanticDebugPrintfInstructions { - NonSemanticDebugPrintfDebugPrintf = 1, - NonSemanticDebugPrintfInstructionsMax = 0x7fffffff -}; - - -#ifdef __cplusplus -} -#endif - -#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/include/SPIRV/NonSemanticShaderDebugInfo100.h b/include/SPIRV/NonSemanticShaderDebugInfo100.h deleted file mode 100644 index f74abcb6..00000000 --- a/include/SPIRV/NonSemanticShaderDebugInfo100.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) 2018 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and/or associated documentation files (the "Materials"), -// to deal in the Materials without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Materials, and to permit persons to whom the -// Materials are furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -// IN THE MATERIALS. - -#ifndef SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_ -#define SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - NonSemanticShaderDebugInfo100Version = 100, - NonSemanticShaderDebugInfo100Version_BitWidthPadding = 0x7fffffff -}; -enum { - NonSemanticShaderDebugInfo100Revision = 6, - NonSemanticShaderDebugInfo100Revision_BitWidthPadding = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100Instructions { - NonSemanticShaderDebugInfo100DebugInfoNone = 0, - NonSemanticShaderDebugInfo100DebugCompilationUnit = 1, - NonSemanticShaderDebugInfo100DebugTypeBasic = 2, - NonSemanticShaderDebugInfo100DebugTypePointer = 3, - NonSemanticShaderDebugInfo100DebugTypeQualifier = 4, - NonSemanticShaderDebugInfo100DebugTypeArray = 5, - NonSemanticShaderDebugInfo100DebugTypeVector = 6, - NonSemanticShaderDebugInfo100DebugTypedef = 7, - NonSemanticShaderDebugInfo100DebugTypeFunction = 8, - NonSemanticShaderDebugInfo100DebugTypeEnum = 9, - NonSemanticShaderDebugInfo100DebugTypeComposite = 10, - NonSemanticShaderDebugInfo100DebugTypeMember = 11, - NonSemanticShaderDebugInfo100DebugTypeInheritance = 12, - NonSemanticShaderDebugInfo100DebugTypePtrToMember = 13, - NonSemanticShaderDebugInfo100DebugTypeTemplate = 14, - NonSemanticShaderDebugInfo100DebugTypeTemplateParameter = 15, - NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter = 16, - NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack = 17, - NonSemanticShaderDebugInfo100DebugGlobalVariable = 18, - NonSemanticShaderDebugInfo100DebugFunctionDeclaration = 19, - NonSemanticShaderDebugInfo100DebugFunction = 20, - NonSemanticShaderDebugInfo100DebugLexicalBlock = 21, - NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator = 22, - NonSemanticShaderDebugInfo100DebugScope = 23, - NonSemanticShaderDebugInfo100DebugNoScope = 24, - NonSemanticShaderDebugInfo100DebugInlinedAt = 25, - NonSemanticShaderDebugInfo100DebugLocalVariable = 26, - NonSemanticShaderDebugInfo100DebugInlinedVariable = 27, - NonSemanticShaderDebugInfo100DebugDeclare = 28, - NonSemanticShaderDebugInfo100DebugValue = 29, - NonSemanticShaderDebugInfo100DebugOperation = 30, - NonSemanticShaderDebugInfo100DebugExpression = 31, - NonSemanticShaderDebugInfo100DebugMacroDef = 32, - NonSemanticShaderDebugInfo100DebugMacroUndef = 33, - NonSemanticShaderDebugInfo100DebugImportedEntity = 34, - NonSemanticShaderDebugInfo100DebugSource = 35, - NonSemanticShaderDebugInfo100DebugFunctionDefinition = 101, - NonSemanticShaderDebugInfo100DebugSourceContinued = 102, - NonSemanticShaderDebugInfo100DebugLine = 103, - NonSemanticShaderDebugInfo100DebugNoLine = 104, - NonSemanticShaderDebugInfo100DebugBuildIdentifier = 105, - NonSemanticShaderDebugInfo100DebugStoragePath = 106, - NonSemanticShaderDebugInfo100DebugEntryPoint = 107, - NonSemanticShaderDebugInfo100DebugTypeMatrix = 108, - NonSemanticShaderDebugInfo100InstructionsMax = 0x7fffffff -}; - - -enum NonSemanticShaderDebugInfo100DebugInfoFlags { - NonSemanticShaderDebugInfo100None = 0x0000, - NonSemanticShaderDebugInfo100FlagIsProtected = 0x01, - NonSemanticShaderDebugInfo100FlagIsPrivate = 0x02, - NonSemanticShaderDebugInfo100FlagIsPublic = 0x03, - NonSemanticShaderDebugInfo100FlagIsLocal = 0x04, - NonSemanticShaderDebugInfo100FlagIsDefinition = 0x08, - NonSemanticShaderDebugInfo100FlagFwdDecl = 0x10, - NonSemanticShaderDebugInfo100FlagArtificial = 0x20, - NonSemanticShaderDebugInfo100FlagExplicit = 0x40, - NonSemanticShaderDebugInfo100FlagPrototyped = 0x80, - NonSemanticShaderDebugInfo100FlagObjectPointer = 0x100, - NonSemanticShaderDebugInfo100FlagStaticMember = 0x200, - NonSemanticShaderDebugInfo100FlagIndirectVariable = 0x400, - NonSemanticShaderDebugInfo100FlagLValueReference = 0x800, - NonSemanticShaderDebugInfo100FlagRValueReference = 0x1000, - NonSemanticShaderDebugInfo100FlagIsOptimized = 0x2000, - NonSemanticShaderDebugInfo100FlagIsEnumClass = 0x4000, - NonSemanticShaderDebugInfo100FlagTypePassByValue = 0x8000, - NonSemanticShaderDebugInfo100FlagTypePassByReference = 0x10000, - NonSemanticShaderDebugInfo100FlagUnknownPhysicalLayout = 0x20000, - NonSemanticShaderDebugInfo100DebugInfoFlagsMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100BuildIdentifierFlags { - NonSemanticShaderDebugInfo100IdentifierPossibleDuplicates = 0x01, - NonSemanticShaderDebugInfo100BuildIdentifierFlagsMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugBaseTypeAttributeEncoding { - NonSemanticShaderDebugInfo100Unspecified = 0, - NonSemanticShaderDebugInfo100Address = 1, - NonSemanticShaderDebugInfo100Boolean = 2, - NonSemanticShaderDebugInfo100Float = 3, - NonSemanticShaderDebugInfo100Signed = 4, - NonSemanticShaderDebugInfo100SignedChar = 5, - NonSemanticShaderDebugInfo100Unsigned = 6, - NonSemanticShaderDebugInfo100UnsignedChar = 7, - NonSemanticShaderDebugInfo100DebugBaseTypeAttributeEncodingMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugCompositeType { - NonSemanticShaderDebugInfo100Class = 0, - NonSemanticShaderDebugInfo100Structure = 1, - NonSemanticShaderDebugInfo100Union = 2, - NonSemanticShaderDebugInfo100DebugCompositeTypeMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugTypeQualifier { - NonSemanticShaderDebugInfo100ConstType = 0, - NonSemanticShaderDebugInfo100VolatileType = 1, - NonSemanticShaderDebugInfo100RestrictType = 2, - NonSemanticShaderDebugInfo100AtomicType = 3, - NonSemanticShaderDebugInfo100DebugTypeQualifierMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugOperation { - NonSemanticShaderDebugInfo100Deref = 0, - NonSemanticShaderDebugInfo100Plus = 1, - NonSemanticShaderDebugInfo100Minus = 2, - NonSemanticShaderDebugInfo100PlusUconst = 3, - NonSemanticShaderDebugInfo100BitPiece = 4, - NonSemanticShaderDebugInfo100Swap = 5, - NonSemanticShaderDebugInfo100Xderef = 6, - NonSemanticShaderDebugInfo100StackValue = 7, - NonSemanticShaderDebugInfo100Constu = 8, - NonSemanticShaderDebugInfo100Fragment = 9, - NonSemanticShaderDebugInfo100DebugOperationMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugImportedEntity { - NonSemanticShaderDebugInfo100ImportedModule = 0, - NonSemanticShaderDebugInfo100ImportedDeclaration = 1, - NonSemanticShaderDebugInfo100DebugImportedEntityMax = 0x7fffffff -}; - - -#ifdef __cplusplus -} -#endif - -#endif // SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_ diff --git a/include/SPIRV/SPVRemapper.cpp b/include/SPIRV/SPVRemapper.cpp deleted file mode 100644 index 84527641..00000000 --- a/include/SPIRV/SPVRemapper.cpp +++ /dev/null @@ -1,1559 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "SPVRemapper.h" -#include "doc.h" - -#include -#include - -namespace spv { - - // By default, just abort on error. Can be overridden via RegisterErrorHandler - spirvbin_t::errorfn_t spirvbin_t::errorHandler = [](const std::string&) { exit(5); }; - // By default, eat log messages. Can be overridden via RegisterLogHandler - spirvbin_t::logfn_t spirvbin_t::logHandler = [](const std::string&) { }; - - // This can be overridden to provide other message behavior if needed - void spirvbin_t::msg(int minVerbosity, int indent, const std::string& txt) const - { - if (verbose >= minVerbosity) - logHandler(std::string(indent, ' ') + txt); - } - - // hash opcode, with special handling for OpExtInst - std::uint32_t spirvbin_t::asOpCodeHash(unsigned word) - { - const spv::Op opCode = asOpCode(word); - - std::uint32_t offset = 0; - - switch (opCode) { - case spv::OpExtInst: - offset += asId(word + 4); break; - default: - break; - } - - return opCode * 19 + offset; // 19 = small prime - } - - spirvbin_t::range_t spirvbin_t::literalRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeFloat: // fall through... - case spv::OpTypePointer: return range_t(2, 3); - case spv::OpTypeInt: return range_t(2, 4); - // TODO: case spv::OpTypeImage: - // TODO: case spv::OpTypeSampledImage: - case spv::OpTypeSampler: return range_t(3, 8); - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypePipe: return range_t(3, 4); - case spv::OpConstant: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::typeRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - if (isConstOp(opCode)) - return range_t(1, 2); - - switch (opCode) { - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypeSampler: // ... - case spv::OpTypeArray: // ... - case spv::OpTypeRuntimeArray: // ... - case spv::OpTypePipe: return range_t(2, 3); - case spv::OpTypeStruct: // fall through - case spv::OpTypeFunction: return range_t(2, maxCount); - case spv::OpTypePointer: return range_t(3, 4); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::constRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeArray: // fall through... - case spv::OpTypeRuntimeArray: return range_t(3, 4); - case spv::OpConstantComposite: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - // Return the size of a type in 32-bit words. This currently only - // handles ints and floats, and is only invoked by queries which must be - // integer types. If ever needed, it can be generalized. - unsigned spirvbin_t::typeSizeInWords(spv::Id id) const - { - const unsigned typeStart = idPos(id); - const spv::Op opCode = asOpCode(typeStart); - - if (errorLatch) - return 0; - - switch (opCode) { - case spv::OpTypeInt: // fall through... - case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32; - default: - return 0; - } - } - - // Looks up the type of a given const or variable ID, and - // returns its size in 32-bit words. - unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const - { - const auto tid_it = idTypeSizeMap.find(id); - if (tid_it == idTypeSizeMap.end()) { - error("type size for ID not found"); - return 0; - } - - return tid_it->second; - } - - // Is this an opcode we should remove when using --strip? - bool spirvbin_t::isStripOp(spv::Op opCode, unsigned start) const - { - switch (opCode) { - case spv::OpSource: - case spv::OpSourceExtension: - case spv::OpName: - case spv::OpMemberName: - case spv::OpLine : - { - const std::string name = literalString(start + 2); - - std::vector::const_iterator it; - for (it = stripWhiteList.begin(); it < stripWhiteList.end(); it++) - { - if (name.find(*it) != std::string::npos) { - return false; - } - } - - return true; - } - default : - return false; - } - } - - // Return true if this opcode is flow control - bool spirvbin_t::isFlowCtrl(spv::Op opCode) const - { - switch (opCode) { - case spv::OpBranchConditional: - case spv::OpBranch: - case spv::OpSwitch: - case spv::OpLoopMerge: - case spv::OpSelectionMerge: - case spv::OpLabel: - case spv::OpFunction: - case spv::OpFunctionEnd: return true; - default: return false; - } - } - - // Return true if this opcode defines a type - bool spirvbin_t::isTypeOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpTypeVoid: - case spv::OpTypeBool: - case spv::OpTypeInt: - case spv::OpTypeFloat: - case spv::OpTypeVector: - case spv::OpTypeMatrix: - case spv::OpTypeImage: - case spv::OpTypeSampler: - case spv::OpTypeArray: - case spv::OpTypeRuntimeArray: - case spv::OpTypeStruct: - case spv::OpTypeOpaque: - case spv::OpTypePointer: - case spv::OpTypeFunction: - case spv::OpTypeEvent: - case spv::OpTypeDeviceEvent: - case spv::OpTypeReserveId: - case spv::OpTypeQueue: - case spv::OpTypeSampledImage: - case spv::OpTypePipe: return true; - default: return false; - } - } - - // Return true if this opcode defines a constant - bool spirvbin_t::isConstOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpConstantSampler: - error("unimplemented constant type"); - return true; - - case spv::OpConstantNull: - case spv::OpConstantTrue: - case spv::OpConstantFalse: - case spv::OpConstantComposite: - case spv::OpConstant: - return true; - - default: - return false; - } - } - - const auto inst_fn_nop = [](spv::Op, unsigned) { return false; }; - const auto op_fn_nop = [](spv::Id&) { }; - - // g++ doesn't like these defined in the class proper in an anonymous namespace. - // Dunno why. Also MSVC doesn't like the constexpr keyword. Also dunno why. - // Defining them externally seems to please both compilers, so, here they are. - const spv::Id spirvbin_t::unmapped = spv::Id(-10000); - const spv::Id spirvbin_t::unused = spv::Id(-10001); - const int spirvbin_t::header_size = 5; - - spv::Id spirvbin_t::nextUnusedId(spv::Id id) - { - while (isNewIdMapped(id)) // search for an unused ID - ++id; - - return id; - } - - spv::Id spirvbin_t::localId(spv::Id id, spv::Id newId) - { - //assert(id != spv::NoResult && newId != spv::NoResult); - - if (id > bound()) { - error(std::string("ID out of range: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (id >= idMapL.size()) - idMapL.resize(id+1, unused); - - if (newId != unmapped && newId != unused) { - if (isOldIdUnused(id)) { - error(std::string("ID unused in module: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (!isOldIdUnmapped(id)) { - error(std::string("ID already mapped: ") + std::to_string(id) + " -> " - + std::to_string(localId(id))); - - return spirvbin_t::unused; - } - - if (isNewIdMapped(newId)) { - error(std::string("ID already used in module: ") + std::to_string(newId)); - return spirvbin_t::unused; - } - - msg(4, 4, std::string("map: ") + std::to_string(id) + " -> " + std::to_string(newId)); - setMapped(newId); - largestNewId = std::max(largestNewId, newId); - } - - return idMapL[id] = newId; - } - - // Parse a literal string from the SPIR binary and return it as an std::string - // Due to C++11 RValue references, this doesn't copy the result string. - std::string spirvbin_t::literalString(unsigned word) const - { - std::string literal; - const spirword_t * pos = spv.data() + word; - - literal.reserve(16); - - do { - spirword_t word = *pos; - for (int i = 0; i < 4; i++) { - char c = word & 0xff; - if (c == '\0') - return literal; - literal += c; - word >>= 8; - } - pos++; - } while (true); - } - - void spirvbin_t::applyMap() - { - msg(3, 2, std::string("Applying map: ")); - - // Map local IDs through the ID map - process(inst_fn_nop, // ignore instructions - [this](spv::Id& id) { - id = localId(id); - - if (errorLatch) - return; - - assert(id != unused && id != unmapped); - } - ); - } - - // Find free IDs for anything we haven't mapped - void spirvbin_t::mapRemainder() - { - msg(3, 2, std::string("Remapping remainder: ")); - - spv::Id unusedId = 1; // can't use 0: that's NoResult - spirword_t maxBound = 0; - - for (spv::Id id = 0; id < idMapL.size(); ++id) { - if (isOldIdUnused(id)) - continue; - - // Find a new mapping for any used but unmapped IDs - if (isOldIdUnmapped(id)) { - localId(id, unusedId = nextUnusedId(unusedId)); - if (errorLatch) - return; - } - - if (isOldIdUnmapped(id)) { - error(std::string("old ID not mapped: ") + std::to_string(id)); - return; - } - - // Track max bound - maxBound = std::max(maxBound, localId(id) + 1); - - if (errorLatch) - return; - } - - bound(maxBound); // reset header ID bound to as big as it now needs to be - } - - // Mark debug instructions for stripping - void spirvbin_t::stripDebug() - { - // Strip instructions in the stripOp set: debug info. - process( - [&](spv::Op opCode, unsigned start) { - // remember opcodes we want to strip later - if (isStripOp(opCode, start)) - stripInst(start); - return true; - }, - op_fn_nop); - } - - // Mark instructions that refer to now-removed IDs for stripping - void spirvbin_t::stripDeadRefs() - { - process( - [&](spv::Op opCode, unsigned start) { - // strip opcodes pointing to removed data - switch (opCode) { - case spv::OpName: - case spv::OpMemberName: - case spv::OpDecorate: - case spv::OpMemberDecorate: - if (idPosR.find(asId(start+1)) == idPosR.end()) - stripInst(start); - break; - default: - break; // leave it alone - } - - return true; - }, - op_fn_nop); - - strip(); - } - - // Update local maps of ID, type, etc positions - void spirvbin_t::buildLocalMaps() - { - msg(2, 2, std::string("build local maps: ")); - - mapped.clear(); - idMapL.clear(); -// preserve nameMap, so we don't clear that. - fnPos.clear(); - fnCalls.clear(); - typeConstPos.clear(); - idPosR.clear(); - entryPoint = spv::NoResult; - largestNewId = 0; - - idMapL.resize(bound(), unused); - - int fnStart = 0; - spv::Id fnRes = spv::NoResult; - - // build local Id and name maps - process( - [&](spv::Op opCode, unsigned start) { - unsigned word = start+1; - spv::Id typeId = spv::NoResult; - - if (spv::InstructionDesc[opCode].hasType()) - typeId = asId(word++); - - // If there's a result ID, remember the size of its type - if (spv::InstructionDesc[opCode].hasResult()) { - const spv::Id resultId = asId(word++); - idPosR[resultId] = start; - - if (typeId != spv::NoResult) { - const unsigned idTypeSize = typeSizeInWords(typeId); - - if (errorLatch) - return false; - - if (idTypeSize != 0) - idTypeSizeMap[resultId] = idTypeSize; - } - } - - if (opCode == spv::Op::OpName) { - const spv::Id target = asId(start+1); - const std::string name = literalString(start+2); - nameMap[name] = target; - - } else if (opCode == spv::Op::OpFunctionCall) { - ++fnCalls[asId(start + 3)]; - } else if (opCode == spv::Op::OpEntryPoint) { - entryPoint = asId(start + 2); - } else if (opCode == spv::Op::OpFunction) { - if (fnStart != 0) { - error("nested function found"); - return false; - } - - fnStart = start; - fnRes = asId(start + 2); - } else if (opCode == spv::Op::OpFunctionEnd) { - assert(fnRes != spv::NoResult); - if (fnStart == 0) { - error("function end without function start"); - return false; - } - - fnPos[fnRes] = range_t(fnStart, start + asWordCount(start)); - fnStart = 0; - } else if (isConstOp(opCode)) { - if (errorLatch) - return false; - - assert(asId(start + 2) != spv::NoResult); - typeConstPos.insert(start); - } else if (isTypeOp(opCode)) { - assert(asId(start + 1) != spv::NoResult); - typeConstPos.insert(start); - } - - return false; - }, - - [this](spv::Id& id) { localId(id, unmapped); } - ); - } - - // Validate the SPIR header - void spirvbin_t::validate() const - { - msg(2, 2, std::string("validating: ")); - - if (spv.size() < header_size) { - error("file too short: "); - return; - } - - if (magic() != spv::MagicNumber) { - error("bad magic number"); - return; - } - - // field 1 = version - // field 2 = generator magic - // field 3 = result bound - - if (schemaNum() != 0) { - error("bad schema, must be 0"); - return; - } - } - - int spirvbin_t::processInstruction(unsigned word, instfn_t instFn, idfn_t idFn) - { - const auto instructionStart = word; - const unsigned wordCount = asWordCount(instructionStart); - const int nextInst = word++ + wordCount; - spv::Op opCode = asOpCode(instructionStart); - - if (nextInst > int(spv.size())) { - error("spir instruction terminated too early"); - return -1; - } - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - if (instFn(opCode, instructionStart)) - return nextInst; - - // Read type and result ID from instruction desc table - if (spv::InstructionDesc[opCode].hasType()) { - idFn(asId(word++)); - --numOperands; - } - - if (spv::InstructionDesc[opCode].hasResult()) { - idFn(asId(word++)); - --numOperands; - } - - // Extended instructions: currently, assume everything is an ID. - // TODO: add whatever data we need for exceptions to that - if (opCode == spv::OpExtInst) { - - idFn(asId(word)); // Instruction set is an ID that also needs to be mapped - - word += 2; // instruction set, and instruction from set - numOperands -= 2; - - for (unsigned op=0; op < numOperands; ++op) - idFn(asId(word++)); // ID - - return nextInst; - } - - // Circular buffer so we can look back at previous unmapped values during the mapping pass. - static const unsigned idBufferSize = 4; - spv::Id idBuffer[idBufferSize]; - unsigned idBufferPos = 0; - - // Store IDs from instruction in our map - for (int op = 0; numOperands > 0; ++op, --numOperands) { - // SpecConstantOp is special: it includes the operands of another opcode which is - // given as a literal in the 3rd word. We will switch over to pretending that the - // opcode being processed is the literal opcode value of the SpecConstantOp. See the - // SPIRV spec for details. This way we will handle IDs and literals as appropriate for - // the embedded op. - if (opCode == spv::OpSpecConstantOp) { - if (op == 0) { - opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp. - --numOperands; - } - } - - switch (spv::InstructionDesc[opCode].operands.getClass(op)) { - case spv::OperandId: - case spv::OperandScope: - case spv::OperandMemorySemantics: - idBuffer[idBufferPos] = asId(word); - idBufferPos = (idBufferPos + 1) % idBufferSize; - idFn(asId(word++)); - break; - - case spv::OperandVariableIds: - for (unsigned i = 0; i < numOperands; ++i) - idFn(asId(word++)); - return nextInst; - - case spv::OperandVariableLiterals: - // for clarity - // if (opCode == spv::OpDecorate && asDecoration(word - 1) == spv::DecorationBuiltIn) { - // ++word; - // --numOperands; - // } - // word += numOperands; - return nextInst; - - case spv::OperandVariableLiteralId: { - if (opCode == OpSwitch) { - // word-2 is the position of the selector ID. OpSwitch Literals match its type. - // In case the IDs are currently being remapped, we get the word[-2] ID from - // the circular idBuffer. - const unsigned literalSizePos = (idBufferPos+idBufferSize-2) % idBufferSize; - const unsigned literalSize = idTypeSizeInWords(idBuffer[literalSizePos]); - const unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize); - - if (errorLatch) - return -1; - - for (unsigned arg=0; arg instPos; - instPos.reserve(unsigned(spv.size()) / 16); // initial estimate; can grow if needed. - - // Build local table of instruction start positions - process( - [&](spv::Op, unsigned start) { instPos.push_back(start); return true; }, - op_fn_nop); - - if (errorLatch) - return; - - // Window size for context-sensitive canonicalization values - // Empirical best size from a single data set. TODO: Would be a good tunable. - // We essentially perform a little convolution around each instruction, - // to capture the flavor of nearby code, to hopefully match to similar - // code in other modules. - static const unsigned windowSize = 2; - - for (unsigned entry = 0; entry < unsigned(instPos.size()); ++entry) { - const unsigned start = instPos[entry]; - const spv::Op opCode = asOpCode(start); - - if (opCode == spv::OpFunction) - fnId = asId(start + 2); - - if (opCode == spv::OpFunctionEnd) - fnId = spv::NoResult; - - if (fnId != spv::NoResult) { // if inside a function - if (spv::InstructionDesc[opCode].hasResult()) { - const unsigned word = start + (spv::InstructionDesc[opCode].hasType() ? 2 : 1); - const spv::Id resId = asId(word); - std::uint32_t hashval = fnId * 17; // small prime - - for (unsigned i = entry-1; i >= entry-windowSize; --i) { - if (asOpCode(instPos[i]) == spv::OpFunction) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - for (unsigned i = entry; i <= entry + windowSize; ++i) { - if (asOpCode(instPos[i]) == spv::OpFunctionEnd) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - - } - } - } - - spv::Op thisOpCode(spv::OpNop); - std::unordered_map opCounter; - int idCounter(0); - fnId = spv::NoResult; - - process( - [&](spv::Op opCode, unsigned start) { - switch (opCode) { - case spv::OpFunction: - // Reset counters at each function - idCounter = 0; - opCounter.clear(); - fnId = asId(start + 2); - break; - - case spv::OpImageSampleImplicitLod: - case spv::OpImageSampleExplicitLod: - case spv::OpImageSampleDrefImplicitLod: - case spv::OpImageSampleDrefExplicitLod: - case spv::OpImageSampleProjImplicitLod: - case spv::OpImageSampleProjExplicitLod: - case spv::OpImageSampleProjDrefImplicitLod: - case spv::OpImageSampleProjDrefExplicitLod: - case spv::OpDot: - case spv::OpCompositeExtract: - case spv::OpCompositeInsert: - case spv::OpVectorShuffle: - case spv::OpLabel: - case spv::OpVariable: - - case spv::OpAccessChain: - case spv::OpLoad: - case spv::OpStore: - case spv::OpCompositeConstruct: - case spv::OpFunctionCall: - ++opCounter[opCode]; - idCounter = 0; - thisOpCode = opCode; - break; - default: - thisOpCode = spv::OpNop; - } - - return false; - }, - - [&](spv::Id& id) { - if (thisOpCode != spv::OpNop) { - ++idCounter; - const std::uint32_t hashval = - // Explicitly cast operands to unsigned int to avoid integer - // promotion to signed int followed by integer overflow, - // which would result in undefined behavior. - static_cast(opCounter[thisOpCode]) - * thisOpCode - * 50047 - + idCounter - + static_cast(fnId) * 117; - - if (isOldIdUnmapped(id)) - localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - } - }); - } - - // EXPERIMENTAL: forward IO and uniform load/stores into operands - // This produces invalid Schema-0 SPIRV - void spirvbin_t::forwardLoadStores() - { - idset_t fnLocalVars; // set of function local vars - idmap_t idMap; // Map of load result IDs to what they load - - // EXPERIMENTAL: Forward input and access chain loads into consumptions - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassUniform || - spv[start+3] == spv::StorageClassUniformConstant || - spv[start+3] == spv::StorageClassInput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpAccessChain && fnLocalVars.count(asId(start+3)) > 0) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - idMap[asId(start+2)] = asId(start+3); - stripInst(start); - } - - return false; - }, - - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - // EXPERIMENTAL: Implicit output stores - fnLocalVars.clear(); - idMap.clear(); - - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassOutput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - idMap[asId(start+2)] = asId(start+1); - stripInst(start); - } - - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - process( - inst_fn_nop, - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // optimize loads and stores - void spirvbin_t::optLoadStore() - { - idset_t fnLocalVars; // candidates for removal (only locals) - idmap_t idMap; // Map of load result IDs to what they load - blockmap_t blockMap; // Map of IDs to blocks they first appear in - int blockNum = 0; // block count, to avoid crossing flow control - - // Find all the function local pointers stored at most once, and not via access chains - process( - [&](spv::Op opCode, unsigned start) { - const int wordCount = asWordCount(start); - - // Count blocks, so we can avoid crossing flow control - if (isFlowCtrl(opCode)) - ++blockNum; - - // Add local variables to the map - if ((opCode == spv::OpVariable && spv[start+3] == spv::StorageClassFunction && asWordCount(start) == 4)) { - fnLocalVars.insert(asId(start+2)); - return true; - } - - // Ignore process vars referenced via access chain - if ((opCode == spv::OpAccessChain || opCode == spv::OpInBoundsAccessChain) && fnLocalVars.count(asId(start+3)) > 0) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - return true; - } - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - const spv::Id varId = asId(start+3); - - // Avoid loads before stores - if (idMap.find(varId) == idMap.end()) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 4 && (spv[start+4] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - const spv::Id varId = asId(start+1); - - if (idMap.find(varId) == idMap.end()) { - idMap[varId] = asId(start+2); - } else { - // Remove if it has more than one store to the same pointer - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 3 && (spv[start+3] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - return false; - }, - - // If local var id used anywhere else, don't eliminate - [&](spv::Id& id) { - if (fnLocalVars.count(id) > 0) { - fnLocalVars.erase(id); - idMap.erase(id); - } - } - ); - - if (errorLatch) - return; - - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) - idMap[asId(start+2)] = idMap[asId(start+3)]; - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - // Chase replacements to their origins, in case there is a chain such as: - // 2 = store 1 - // 3 = load 2 - // 4 = store 3 - // 5 = load 4 - // We want to replace uses of 5 with 1. - for (const auto& idPair : idMap) { - spv::Id id = idPair.first; - while (idMap.find(id) != idMap.end()) // Chase to end of chain - id = idMap[id]; - - idMap[idPair.first] = id; // replace with final result - } - - // Remove the load/store/variables for the ones we've discovered - process( - [&](spv::Op opCode, unsigned start) { - if ((opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) || - (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) || - (opCode == spv::OpVariable && fnLocalVars.count(asId(start+2)) > 0)) { - - stripInst(start); - return true; - } - - return false; - }, - - [&](spv::Id& id) { - if (idMap.find(id) != idMap.end()) id = idMap[id]; - } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // remove bodies of uncalled functions - void spirvbin_t::dceFuncs() - { - msg(3, 2, std::string("Removing Dead Functions: ")); - - // TODO: There are more efficient ways to do this. - bool changed = true; - - while (changed) { - changed = false; - - for (auto fn = fnPos.begin(); fn != fnPos.end(); ) { - if (fn->first == entryPoint) { // don't DCE away the entry point! - ++fn; - continue; - } - - const auto call_it = fnCalls.find(fn->first); - - if (call_it == fnCalls.end() || call_it->second == 0) { - changed = true; - stripRange.push_back(fn->second); - - // decrease counts of called functions - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::Op::OpFunctionCall) { - const auto call_it = fnCalls.find(asId(start + 3)); - if (call_it != fnCalls.end()) { - if (--call_it->second <= 0) - fnCalls.erase(call_it); - } - } - - return true; - }, - op_fn_nop, - fn->second.first, - fn->second.second); - - if (errorLatch) - return; - - fn = fnPos.erase(fn); - } else ++fn; - } - } - } - - // remove unused function variables + decorations - void spirvbin_t::dceVars() - { - msg(3, 2, std::string("DCE Vars: ")); - - std::unordered_map varUseCount; - - // Count function variable use - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpVariable) { - ++varUseCount[asId(start+2)]; - return true; - } else if (opCode == spv::OpEntryPoint) { - const int wordCount = asWordCount(start); - for (int i = 4; i < wordCount; i++) { - ++varUseCount[asId(start+i)]; - } - return true; - } else - return false; - }, - - [&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single-use function variables + associated decorations and names - process( - [&](spv::Op opCode, unsigned start) { - spv::Id id = spv::NoResult; - if (opCode == spv::OpVariable) - id = asId(start+2); - if (opCode == spv::OpDecorate || opCode == spv::OpName) - id = asId(start+1); - - if (id != spv::NoResult && varUseCount[id] == 1) - stripInst(start); - - return true; - }, - op_fn_nop); - } - - // remove unused types - void spirvbin_t::dceTypes() - { - std::vector isType(bound(), false); - - // for speed, make O(1) way to get to type query (map is log(n)) - for (const auto typeStart : typeConstPos) - isType[asTypeConstId(typeStart)] = true; - - std::unordered_map typeUseCount; - - // This is not the most efficient algorithm, but this is an offline tool, and - // it's easy to write this way. Can be improved opportunistically if needed. - bool changed = true; - while (changed) { - changed = false; - strip(); - typeUseCount.clear(); - - // Count total type usage - process(inst_fn_nop, - [&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single reference types - for (const auto typeStart : typeConstPos) { - const spv::Id typeId = asTypeConstId(typeStart); - if (typeUseCount[typeId] == 1) { - changed = true; - --typeUseCount[typeId]; - stripInst(typeStart); - } - } - - if (errorLatch) - return; - } - } - -#ifdef NOTDEF - bool spirvbin_t::matchType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const - { - // Find the local type id "lt" and global type id "gt" - const auto lt_it = typeConstPosR.find(lt); - if (lt_it == typeConstPosR.end()) - return false; - - const auto typeStart = lt_it->second; - - // Search for entry in global table - const auto gtype = globalTypes.find(gt); - if (gtype == globalTypes.end()) - return false; - - const auto& gdata = gtype->second; - - // local wordcount and opcode - const int wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - // no type match if opcodes don't match, or operand count doesn't match - if (opCode != opOpCode(gdata[0]) || wordCount != opWordCount(gdata[0])) - return false; - - const unsigned numOperands = wordCount - 2; // all types have a result - - const auto cmpIdRange = [&](range_t range) { - for (int x=range.first; xsecond; - } - - // Hash types to canonical values. This can return ID collisions (it's a bit - // inevitable): it's up to the caller to handle that gracefully. - std::uint32_t spirvbin_t::hashType(unsigned typeStart) const - { - const unsigned wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - switch (opCode) { - case spv::OpTypeVoid: return 0; - case spv::OpTypeBool: return 1; - case spv::OpTypeInt: return 3 + (spv[typeStart+3]); - case spv::OpTypeFloat: return 5; - case spv::OpTypeVector: - return 6 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeMatrix: - return 30 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeImage: - return 120 + hashType(idPos(spv[typeStart+2])) + - spv[typeStart+3] + // dimensionality - spv[typeStart+4] * 8 * 16 + // depth - spv[typeStart+5] * 4 * 16 + // arrayed - spv[typeStart+6] * 2 * 16 + // multisampled - spv[typeStart+7] * 1 * 16; // format - case spv::OpTypeSampler: - return 500; - case spv::OpTypeSampledImage: - return 502; - case spv::OpTypeArray: - return 501 + hashType(idPos(spv[typeStart+2])) * spv[typeStart+3]; - case spv::OpTypeRuntimeArray: - return 5000 + hashType(idPos(spv[typeStart+2])); - case spv::OpTypeStruct: - { - std::uint32_t hash = 10000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeOpaque: return 6000 + spv[typeStart+2]; - case spv::OpTypePointer: return 100000 + hashType(idPos(spv[typeStart+3])); - case spv::OpTypeFunction: - { - std::uint32_t hash = 200000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeEvent: return 300000; - case spv::OpTypeDeviceEvent: return 300001; - case spv::OpTypeReserveId: return 300002; - case spv::OpTypeQueue: return 300003; - case spv::OpTypePipe: return 300004; - case spv::OpConstantTrue: return 300007; - case spv::OpConstantFalse: return 300008; - case spv::OpConstantComposite: - { - std::uint32_t hash = 300011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - case spv::OpConstant: - { - std::uint32_t hash = 400011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * spv[typeStart+w]; - return hash; - } - case spv::OpConstantNull: - { - std::uint32_t hash = 500009 + hashType(idPos(spv[typeStart+1])); - return hash; - } - case spv::OpConstantSampler: - { - std::uint32_t hash = 600011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * spv[typeStart+w]; - return hash; - } - - default: - error("unknown type opcode"); - return 0; - } - } - - void spirvbin_t::mapTypeConst() - { - globaltypes_t globalTypeMap; - - msg(3, 2, std::string("Remapping Consts & Types: ")); - - static const std::uint32_t softTypeIdLimit = 3011; // small prime. TODO: get from options - static const std::uint32_t firstMappedID = 8; // offset into ID space - - for (auto& typeStart : typeConstPos) { - const spv::Id resId = asTypeConstId(typeStart); - const std::uint32_t hashval = hashType(typeStart); - - if (errorLatch) - return; - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - } - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::strip() - { - if (stripRange.empty()) // nothing to do - return; - - // Sort strip ranges in order of traversal - std::sort(stripRange.begin(), stripRange.end()); - - // Allocate a new binary big enough to hold old binary - // We'll step this iterator through the strip ranges as we go through the binary - auto strip_it = stripRange.begin(); - - int strippedPos = 0; - for (unsigned word = 0; word < unsigned(spv.size()); ++word) { - while (strip_it != stripRange.end() && word >= strip_it->second) - ++strip_it; - - if (strip_it == stripRange.end() || word < strip_it->first || word >= strip_it->second) - spv[strippedPos++] = spv[word]; - } - - spv.resize(strippedPos); - stripRange.clear(); - - buildLocalMaps(); - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::remap(std::uint32_t opts) - { - options = opts; - - // Set up opcode tables from SpvDoc - spv::Parameterize(); - - validate(); // validate header - buildLocalMaps(); // build ID maps - - msg(3, 4, std::string("ID bound: ") + std::to_string(bound())); - - if (options & STRIP) stripDebug(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - if (options & OPT_LOADSTORE) optLoadStore(); - if (errorLatch) return; - - if (options & OPT_FWD_LS) forwardLoadStores(); - if (errorLatch) return; - - if (options & DCE_FUNCS) dceFuncs(); - if (errorLatch) return; - - if (options & DCE_VARS) dceVars(); - if (errorLatch) return; - - if (options & DCE_TYPES) dceTypes(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - stripDeadRefs(); // remove references to things we DCEed - if (errorLatch) return; - - // after the last strip, we must clean any debug info referring to now-deleted data - - if (options & MAP_TYPES) mapTypeConst(); - if (errorLatch) return; - - if (options & MAP_NAMES) mapNames(); - if (errorLatch) return; - - if (options & MAP_FUNCS) mapFnBodies(); - if (errorLatch) return; - - if (options & MAP_ALL) { - mapRemainder(); // map any unmapped IDs - if (errorLatch) return; - - applyMap(); // Now remap each shader to the new IDs we've come up with - if (errorLatch) return; - } - } - - // remap from a memory image - void spirvbin_t::remap(std::vector& in_spv, const std::vector& whiteListStrings, - std::uint32_t opts) - { - stripWhiteList = whiteListStrings; - spv.swap(in_spv); - remap(opts); - spv.swap(in_spv); - } - - // remap from a memory image - legacy interface without white list - void spirvbin_t::remap(std::vector& in_spv, std::uint32_t opts) - { - stripWhiteList.clear(); - spv.swap(in_spv); - remap(opts); - spv.swap(in_spv); - } - -} // namespace SPV - diff --git a/include/SPIRV/SPVRemapper.h b/include/SPIRV/SPVRemapper.h deleted file mode 100644 index e60da792..00000000 --- a/include/SPIRV/SPVRemapper.h +++ /dev/null @@ -1,300 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef SPIRVREMAPPER_H -#define SPIRVREMAPPER_H - -#include -#include -#include -#include - -#ifdef GLSLANG_IS_SHARED_LIBRARY - #ifdef _WIN32 - #ifdef GLSLANG_EXPORTING - #define GLSLANG_EXPORT __declspec(dllexport) - #else - #define GLSLANG_EXPORT __declspec(dllimport) - #endif - #elif __GNUC__ >= 4 - #define GLSLANG_EXPORT __attribute__((visibility("default"))) - #endif -#endif // GLSLANG_IS_SHARED_LIBRARY -#ifndef GLSLANG_EXPORT -#define GLSLANG_EXPORT -#endif - -namespace spv { - -class spirvbin_base_t -{ -public: - enum Options { - NONE = 0, - STRIP = (1<<0), - MAP_TYPES = (1<<1), - MAP_NAMES = (1<<2), - MAP_FUNCS = (1<<3), - DCE_FUNCS = (1<<4), - DCE_VARS = (1<<5), - DCE_TYPES = (1<<6), - OPT_LOADSTORE = (1<<7), - OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV - MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), - DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), - OPT_ALL = (OPT_LOADSTORE), - - ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), - DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) - }; -}; - -} // namespace SPV - -#include -#include -#include -#include -#include -#include -#include - -#include "spirv.hpp" - -namespace spv { - -static inline constexpr Id NoResult = 0; - -// class to hold SPIR-V binary data for remapping, DCE, and debug stripping -class GLSLANG_EXPORT spirvbin_t : public spirvbin_base_t -{ -public: - spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) - { } - - virtual ~spirvbin_t() { } - - // remap on an existing binary in memory - void remap(std::vector& spv, const std::vector& whiteListStrings, - std::uint32_t opts = DO_EVERYTHING); - - // remap on an existing binary in memory - legacy interface without white list - void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); - - // Type for error/log handler functions - typedef std::function errorfn_t; - typedef std::function logfn_t; - - // Register error/log handling functions (can be lambda fn / functor / etc) - static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } - static void registerLogHandler(logfn_t handler) { logHandler = handler; } - -protected: - // This can be overridden to provide other message behavior if needed - virtual void msg(int minVerbosity, int indent, const std::string& txt) const; - -private: - // Local to global, or global to local ID map - typedef std::unordered_map idmap_t; - typedef std::unordered_set idset_t; - typedef std::unordered_map blockmap_t; - - void remap(std::uint32_t opts = DO_EVERYTHING); - - // Map of names to IDs - typedef std::unordered_map namemap_t; - - typedef std::uint32_t spirword_t; - - typedef std::pair range_t; - typedef std::function idfn_t; - typedef std::function instfn_t; - - // Special Values for ID map: - static const spv::Id unmapped; // unchanged from default value - static const spv::Id unused; // unused ID - static const int header_size; // SPIR header = 5 words - - class id_iterator_t; - - // For mapping type entries between different shaders - typedef std::vector typeentry_t; - typedef std::map globaltypes_t; - - // A set that preserves position order, and a reverse map - typedef std::set posmap_t; - typedef std::unordered_map posmap_rev_t; - - // Maps and ID to the size of its base type, if known. - typedef std::unordered_map typesize_map_t; - - // handle error - void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } - - bool isConstOp(spv::Op opCode) const; - bool isTypeOp(spv::Op opCode) const; - bool isStripOp(spv::Op opCode) const; - bool isFlowCtrl(spv::Op opCode) const; - range_t literalRange(spv::Op opCode) const; - range_t typeRange(spv::Op opCode) const; - range_t constRange(spv::Op opCode) const; - unsigned typeSizeInWords(spv::Id id) const; - unsigned idTypeSizeInWords(spv::Id id) const; - - bool isStripOp(spv::Op opCode, unsigned start) const; - - spv::Id& asId(unsigned word) { return spv[word]; } - const spv::Id& asId(unsigned word) const { return spv[word]; } - spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } - std::uint32_t asOpCodeHash(unsigned word); - spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } - unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } - spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } - unsigned idPos(spv::Id id) const; - - static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } - static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } - - // Header access & set methods - spirword_t magic() const { return spv[0]; } // return magic number - spirword_t bound() const { return spv[3]; } // return Id bound from header - spirword_t bound(spirword_t b) { return spv[3] = b; } - spirword_t genmagic() const { return spv[2]; } // generator magic - spirword_t genmagic(spirword_t m) { return spv[2] = m; } - spirword_t schemaNum() const { return spv[4]; } // schema number from header - - // Mapping fns: get - spv::Id localId(spv::Id id) const { return idMapL[id]; } - - // Mapping fns: set - inline spv::Id localId(spv::Id id, spv::Id newId); - void countIds(spv::Id id); - - // Return next unused new local ID. - // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), - // which std::vector doens't have. - inline spv::Id nextUnusedId(spv::Id id); - - void buildLocalMaps(); - std::string literalString(unsigned word) const; // Return literal as a std::string - int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } - - bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } - bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } - bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } - bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } - bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } - - // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; - // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; - std::uint32_t hashType(unsigned typeStart) const; - - spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); - int processInstruction(unsigned word, instfn_t, idfn_t); - - void validate() const; - void mapTypeConst(); - void mapFnBodies(); - void optLoadStore(); - void dceFuncs(); - void dceVars(); - void dceTypes(); - void mapNames(); - void foldIds(); // fold IDs to smallest space - void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) - void offsetIds(); // create relative offset IDs - - void applyMap(); // remap per local name map - void mapRemainder(); // map any IDs we haven't touched yet - void stripDebug(); // strip all debug info - void stripDeadRefs(); // strips debug info for now-dead references after DCE - void strip(); // remove debug symbols - - std::vector spv; // SPIR words - - std::vector stripWhiteList; - - namemap_t nameMap; // ID names from OpName - - // Since we want to also do binary ops, we can't use std::vector. we could use - // boost::dynamic_bitset, but we're trying to avoid a boost dependency. - typedef std::uint64_t bits_t; - std::vector mapped; // which new IDs have been mapped - static const int mBits = sizeof(bits_t) * 4; - - bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } - void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } - void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } - size_t maxMappedId() const { return mapped.size() * mBits; } - - // Add a strip range for a given instruction starting at 'start' - // Note: avoiding brace initializers to please older versions os MSVC. - void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } - - // Function start and end. use unordered_map because we'll have - // many fewer functions than IDs. - std::unordered_map fnPos; - - // Which functions are called, anywhere in the module, with a call count - std::unordered_map fnCalls; - - posmap_t typeConstPos; // word positions that define types & consts (ordered) - posmap_rev_t idPosR; // reverse map from IDs to positions - typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. - - std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs - - spv::Id entryPoint; // module entry point - spv::Id largestNewId; // biggest new ID we have mapped anything to - - // Sections of the binary to strip, given as [begin,end) - std::vector stripRange; - - // processing options: - std::uint32_t options; - int verbose; // verbosity level - - // Error latch: this is set if the error handler is ever executed. It would be better to - // use a try/catch block and throw, but that's not desired for certain environments, so - // this is the alternative. - mutable bool errorLatch; - - static errorfn_t errorHandler; - static logfn_t logHandler; -}; - -} // namespace SPV - -#endif // SPIRVREMAPPER_H diff --git a/include/SPIRV/SpvBuilder.cpp b/include/SPIRV/SpvBuilder.cpp deleted file mode 100644 index e23ccabe..00000000 --- a/include/SPIRV/SpvBuilder.cpp +++ /dev/null @@ -1,4482 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Helper for making SPIR-V IR. Generally, this is documented in the header -// SpvBuilder.h. -// - -#include -#include - -#include -#include - -#include "SpvBuilder.h" -#include "hex_float.h" - -#ifndef _WIN32 - #include -#endif - -namespace spv { - -Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) : - spvVersion(spvVersion), - sourceLang(SourceLanguageUnknown), - sourceVersion(0), - addressModel(AddressingModelLogical), - memoryModel(MemoryModelGLSL450), - builderNumber(magicNumber), - buildPoint(nullptr), - uniqueId(0), - entryPointFunction(nullptr), - generatingOpCodeForSpecConst(false), - logger(buildLogger) -{ - clearAccessChain(); -} - -Builder::~Builder() -{ -} - -Id Builder::import(const char* name) -{ - Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); - import->addStringOperand(name); - module.mapInstruction(import); - - imports.push_back(std::unique_ptr(import)); - return import->getResultId(); -} - -// For creating new groupedTypes (will return old type if the requested one was already made). -Id Builder::makeVoidType() -{ - Instruction* type; - if (groupedTypes[OpTypeVoid].size() == 0) { - Id typeId = getUniqueId(); - type = new Instruction(typeId, NoType, OpTypeVoid); - groupedTypes[OpTypeVoid].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - // Core OpTypeVoid used for debug void type - if (emitNonSemanticShaderDebugInfo) - debugId[typeId] = typeId; - } else - type = groupedTypes[OpTypeVoid].back(); - - return type->getResultId(); -} - -Id Builder::makeBoolType() -{ - Instruction* type; - if (groupedTypes[OpTypeBool].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeBool); - groupedTypes[OpTypeBool].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) { - auto const debugResultId = makeBoolDebugType(32); - debugId[type->getResultId()] = debugResultId; - } - - } else - type = groupedTypes[OpTypeBool].back(); - - - return type->getResultId(); -} - -Id Builder::makeSamplerType() -{ - Instruction* type; - if (groupedTypes[OpTypeSampler].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeSampler); - groupedTypes[OpTypeSampler].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeSampler].back(); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeCompositeDebugType({}, "type.sampler", NonSemanticShaderDebugInfo100Structure, true); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makePointer(StorageClass storageClass, Id pointee) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)storageClass && - type->getIdOperand(1) == pointee) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypePointer); - type->reserveOperands(2); - type->addImmediateOperand(storageClass); - type->addIdOperand(pointee); - groupedTypes[OpTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) { - const Id debugResultId = makePointerDebugType(storageClass, pointee); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeForwardPointer(StorageClass storageClass) -{ - // Caching/uniquifying doesn't work here, because we don't know the - // pointee type and there can be multiple forward pointers of the same - // storage type. Somebody higher up in the stack must keep track. - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer); - type->addImmediateOperand(storageClass); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) { - const Id debugResultId = makeForwardPointerDebugType(storageClass); - debugId[type->getResultId()] = debugResultId; - } - return type->getResultId(); -} - -Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)storageClass && - type->getIdOperand(1) == pointee) - return type->getResultId(); - } - - type = new Instruction(forwardPointerType, NoType, OpTypePointer); - type->reserveOperands(2); - type->addImmediateOperand(storageClass); - type->addIdOperand(pointee); - groupedTypes[OpTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // If we are emitting nonsemantic debuginfo, we need to patch the debug pointer type - // that was emitted alongside the forward pointer, now that we have a pointee debug - // type for it to point to. - if (emitNonSemanticShaderDebugInfo) { - Instruction *debugForwardPointer = module.getInstruction(debugId[forwardPointerType]); - assert(debugId[pointee]); - debugForwardPointer->setIdOperand(2, debugId[pointee]); - } - - return type->getResultId(); -} - -Id Builder::makeIntegerType(int width, bool hasSign) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) { - type = groupedTypes[OpTypeInt][t]; - if (type->getImmediateOperand(0) == (unsigned)width && - type->getImmediateOperand(1) == (hasSign ? 1u : 0u)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeInt); - type->reserveOperands(2); - type->addImmediateOperand(width); - type->addImmediateOperand(hasSign ? 1 : 0); - groupedTypes[OpTypeInt].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 8: - case 16: - // these are currently handled by storage-type declarations and post processing - break; - case 64: - addCapability(CapabilityInt64); - break; - default: - break; - } - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeIntegerDebugType(width, hasSign); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeFloatType(int width) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) { - type = groupedTypes[OpTypeFloat][t]; - if (type->getImmediateOperand(0) == (unsigned)width) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeFloat); - type->addImmediateOperand(width); - groupedTypes[OpTypeFloat].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 16: - // currently handled by storage-type declarations and post processing - break; - case 64: - addCapability(CapabilityFloat64); - break; - default: - break; - } - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeFloatDebugType(width); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -// Make a struct without checking for duplication. -// See makeStructResultType() for non-decorated structs -// needed as the result of some instructions, which does -// check for duplicates. -Id Builder::makeStructType(const std::vector& members, const char* name, bool const compilerGenerated) -{ - // Don't look for previous one, because in the general case, - // structs can be duplicated except for decorations. - - // not found, make it - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct); - for (int op = 0; op < (int)members.size(); ++op) - type->addIdOperand(members[op]); - groupedTypes[OpTypeStruct].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - addName(type->getResultId(), name); - - if (emitNonSemanticShaderDebugInfo && !compilerGenerated) - { - auto const debugResultId = makeCompositeDebugType(members, name, NonSemanticShaderDebugInfo100Structure); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -// Make a struct for the simple results of several instructions, -// checking for duplication. -Id Builder::makeStructResultType(Id type0, Id type1) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) { - type = groupedTypes[OpTypeStruct][t]; - if (type->getNumOperands() != 2) - continue; - if (type->getIdOperand(0) != type0 || - type->getIdOperand(1) != type1) - continue; - return type->getResultId(); - } - - // not found, make it - std::vector members; - members.push_back(type0); - members.push_back(type1); - - return makeStructType(members, "ResType"); -} - -Id Builder::makeVectorType(Id component, int size) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) { - type = groupedTypes[OpTypeVector][t]; - if (type->getIdOperand(0) == component && - type->getImmediateOperand(1) == (unsigned)size) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeVector); - type->reserveOperands(2); - type->addIdOperand(component); - type->addImmediateOperand(size); - groupedTypes[OpTypeVector].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeVectorDebugType(component, size); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeMatrixType(Id component, int cols, int rows) -{ - assert(cols <= maxMatrixSize && rows <= maxMatrixSize); - - Id column = makeVectorType(component, rows); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) { - type = groupedTypes[OpTypeMatrix][t]; - if (type->getIdOperand(0) == column && - type->getImmediateOperand(1) == (unsigned)cols) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeMatrix); - type->reserveOperands(2); - type->addIdOperand(column); - type->addImmediateOperand(cols); - groupedTypes[OpTypeMatrix].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeMatrixDebugType(column, cols); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id cols, Id use) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeCooperativeMatrixKHR].size(); ++t) { - type = groupedTypes[OpTypeCooperativeMatrixKHR][t]; - if (type->getIdOperand(0) == component && - type->getIdOperand(1) == scope && - type->getIdOperand(2) == rows && - type->getIdOperand(3) == cols && - type->getIdOperand(4) == use) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeCooperativeMatrixKHR); - type->reserveOperands(5); - type->addIdOperand(component); - type->addIdOperand(scope); - type->addIdOperand(rows); - type->addIdOperand(cols); - type->addIdOperand(use); - groupedTypes[OpTypeCooperativeMatrixKHR].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - // Find a name for one of the parameters. It can either come from debuginfo for another - // type, or an OpName from a constant. - auto const findName = [&](Id id) { - Id id2 = debugId[id]; - for (auto &t : groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic]) { - if (t->getResultId() == id2) { - for (auto &s : strings) { - if (s->getResultId() == t->getIdOperand(2)) { - return s->getNameString(); - } - } - } - } - for (auto &t : names) { - if (t->getIdOperand(0) == id) { - return t->getNameString(); - } - } - return "unknown"; - }; - std::string debugName = "coopmat<"; - debugName += std::string(findName(component)) + ", "; - if (isConstantScalar(scope)) { - debugName += std::string("gl_Scope") + std::string(spv::ScopeToString((spv::Scope)getConstantScalar(scope))) + ", "; - } else { - debugName += std::string(findName(scope)) + ", "; - } - debugName += std::string(findName(rows)) + ", "; - debugName += std::string(findName(cols)) + ">"; - // There's no nonsemantic debug info instruction for cooperative matrix types, - // use opaque composite instead. - auto const debugResultId = makeCompositeDebugType({}, debugName.c_str(), NonSemanticShaderDebugInfo100Structure, true); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeCooperativeMatrixTypeNV(Id component, Id scope, Id rows, Id cols) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeCooperativeMatrixNV].size(); ++t) { - type = groupedTypes[OpTypeCooperativeMatrixNV][t]; - if (type->getIdOperand(0) == component && type->getIdOperand(1) == scope && type->getIdOperand(2) == rows && - type->getIdOperand(3) == cols) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeCooperativeMatrixNV); - type->reserveOperands(4); - type->addIdOperand(component); - type->addIdOperand(scope); - type->addIdOperand(rows); - type->addIdOperand(cols); - groupedTypes[OpTypeCooperativeMatrixNV].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeCooperativeMatrixTypeWithSameShape(Id component, Id otherType) -{ - Instruction* instr = module.getInstruction(otherType); - if (instr->getOpCode() == OpTypeCooperativeMatrixNV) { - return makeCooperativeMatrixTypeNV(component, instr->getIdOperand(1), instr->getIdOperand(2), instr->getIdOperand(3)); - } else { - assert(instr->getOpCode() == OpTypeCooperativeMatrixKHR); - return makeCooperativeMatrixTypeKHR(component, instr->getIdOperand(1), instr->getIdOperand(2), instr->getIdOperand(3), instr->getIdOperand(4)); - } -} - -Id Builder::makeGenericType(spv::Op opcode, std::vector& operands) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[opcode].size(); ++t) { - type = groupedTypes[opcode][t]; - if (static_cast(type->getNumOperands()) != operands.size()) - continue; // Number mismatch, find next - - bool match = true; - for (int op = 0; match && op < (int)operands.size(); ++op) { - match = (operands[op].isId ? type->getIdOperand(op) : type->getImmediateOperand(op)) == operands[op].word; - } - if (match) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, opcode); - type->reserveOperands(operands.size()); - for (size_t op = 0; op < operands.size(); ++op) { - if (operands[op].isId) - type->addIdOperand(operands[op].word); - else - type->addImmediateOperand(operands[op].word); - } - groupedTypes[opcode].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -// TODO: performance: track arrays per stride -// If a stride is supplied (non-zero) make an array. -// If no stride (0), reuse previous array types. -// 'size' is an Id of a constant or specialization constant of the array size -Id Builder::makeArrayType(Id element, Id sizeId, int stride) -{ - Instruction* type; - if (stride == 0) { - // try to find existing type - for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) { - type = groupedTypes[OpTypeArray][t]; - if (type->getIdOperand(0) == element && - type->getIdOperand(1) == sizeId) - return type->getResultId(); - } - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeArray); - type->reserveOperands(2); - type->addIdOperand(element); - type->addIdOperand(sizeId); - groupedTypes[OpTypeArray].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeArrayDebugType(element, sizeId); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeRuntimeArray(Id element) -{ - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray); - type->addIdOperand(element); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeArrayDebugType(element, makeUintConstant(0)); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) { - type = groupedTypes[OpTypeFunction][t]; - if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1) - continue; - bool mismatch = false; - for (int p = 0; p < (int)paramTypes.size(); ++p) { - if (paramTypes[p] != type->getIdOperand(p + 1)) { - mismatch = true; - break; - } - } - if (! mismatch) - { - // If compiling HLSL, glslang will create a wrapper function around the entrypoint. Accordingly, a void(void) - // function type is created for the wrapper function. However, nonsemantic shader debug information is disabled - // while creating the HLSL wrapper. Consequently, if we encounter another void(void) function, we need to create - // the associated debug function type if it hasn't been created yet. - if(emitNonSemanticShaderDebugInfo && debugId[type->getResultId()] == 0) { - assert(sourceLang == spv::SourceLanguageHLSL); - assert(getTypeClass(returnType) == OpTypeVoid && paramTypes.size() == 0); - - Id debugTypeId = makeDebugFunctionType(returnType, {}); - debugId[type->getResultId()] = debugTypeId; - } - return type->getResultId(); - } - } - - // not found, make it - Id typeId = getUniqueId(); - type = new Instruction(typeId, NoType, OpTypeFunction); - type->reserveOperands(paramTypes.size() + 1); - type->addIdOperand(returnType); - for (int p = 0; p < (int)paramTypes.size(); ++p) - type->addIdOperand(paramTypes[p]); - groupedTypes[OpTypeFunction].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // make debug type and map it - if (emitNonSemanticShaderDebugInfo) { - Id debugTypeId = makeDebugFunctionType(returnType, paramTypes); - debugId[typeId] = debugTypeId; - } - - return type->getResultId(); -} - -Id Builder::makeDebugFunctionType(Id returnType, const std::vector& paramTypes) -{ - assert(debugId[returnType] != 0); - - Id typeId = getUniqueId(); - auto type = new Instruction(typeId, makeVoidType(), OpExtInst); - type->reserveOperands(paramTypes.size() + 4); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeFunction); - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); - type->addIdOperand(debugId[returnType]); - for (auto const paramType : paramTypes) { - if (isPointerType(paramType) || isArrayType(paramType)) { - type->addIdOperand(debugId[getContainedTypeId(paramType)]); - } - else { - type->addIdOperand(debugId[paramType]); - } - } - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - return typeId; -} - -Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, - ImageFormat format) -{ - assert(sampled == 1 || sampled == 2); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) { - type = groupedTypes[OpTypeImage][t]; - if (type->getIdOperand(0) == sampledType && - type->getImmediateOperand(1) == (unsigned int)dim && - type->getImmediateOperand(2) == ( depth ? 1u : 0u) && - type->getImmediateOperand(3) == (arrayed ? 1u : 0u) && - type->getImmediateOperand(4) == ( ms ? 1u : 0u) && - type->getImmediateOperand(5) == sampled && - type->getImmediateOperand(6) == (unsigned int)format) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeImage); - type->reserveOperands(7); - type->addIdOperand(sampledType); - type->addImmediateOperand( dim); - type->addImmediateOperand( depth ? 1 : 0); - type->addImmediateOperand(arrayed ? 1 : 0); - type->addImmediateOperand( ms ? 1 : 0); - type->addImmediateOperand(sampled); - type->addImmediateOperand((unsigned int)format); - - groupedTypes[OpTypeImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (dim) { - case DimBuffer: - if (sampled == 1) - addCapability(CapabilitySampledBuffer); - else - addCapability(CapabilityImageBuffer); - break; - case Dim1D: - if (sampled == 1) - addCapability(CapabilitySampled1D); - else - addCapability(CapabilityImage1D); - break; - case DimCube: - if (arrayed) { - if (sampled == 1) - addCapability(CapabilitySampledCubeArray); - else - addCapability(CapabilityImageCubeArray); - } - break; - case DimRect: - if (sampled == 1) - addCapability(CapabilitySampledRect); - else - addCapability(CapabilityImageRect); - break; - case DimSubpassData: - addCapability(CapabilityInputAttachment); - break; - default: - break; - } - - if (ms) { - if (sampled == 2) { - // Images used with subpass data are not storage - // images, so don't require the capability for them. - if (dim != Dim::DimSubpassData) - addCapability(CapabilityStorageImageMultisample); - if (arrayed) - addCapability(CapabilityImageMSArray); - } - } - - if (emitNonSemanticShaderDebugInfo) - { - auto TypeName = [&dim]() -> char const* { - switch (dim) { - case Dim1D: return "type.1d.image"; - case Dim2D: return "type.2d.image"; - case Dim3D: return "type.3d.image"; - case DimCube: return "type.cube.image"; - default: return "type.image"; - } - }; - - auto const debugResultId = makeCompositeDebugType({}, TypeName(), NonSemanticShaderDebugInfo100Class, true); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeSampledImageType(Id imageType) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) { - type = groupedTypes[OpTypeSampledImage][t]; - if (type->getIdOperand(0) == imageType) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage); - type->addIdOperand(imageType); - - groupedTypes[OpTypeSampledImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeCompositeDebugType({}, "type.sampled.image", NonSemanticShaderDebugInfo100Class, true); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeDebugInfoNone() -{ - if (debugInfoNone != 0) - return debugInfoNone; - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->reserveOperands(2); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugInfoNone); - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - debugInfoNone = inst->getResultId(); - - return debugInfoNone; -} - -Id Builder::makeBoolDebugType(int const size) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == getStringId("bool") && - type->getIdOperand(1) == static_cast(size) && - type->getIdOperand(2) == NonSemanticShaderDebugInfo100Boolean) - return type->getResultId(); - } - - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(6); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - - type->addIdOperand(getStringId("bool")); // name id - type->addIdOperand(makeUintConstant(size)); // size id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Boolean)); // encoding id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeIntegerDebugType(int const width, bool const hasSign) -{ - const char* typeName = nullptr; - switch (width) { - case 8: typeName = hasSign ? "int8_t" : "uint8_t"; break; - case 16: typeName = hasSign ? "int16_t" : "uint16_t"; break; - case 64: typeName = hasSign ? "int64_t" : "uint64_t"; break; - default: typeName = hasSign ? "int" : "uint"; - } - auto nameId = getStringId(typeName); - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == nameId && - type->getIdOperand(1) == static_cast(width) && - type->getIdOperand(2) == (hasSign ? NonSemanticShaderDebugInfo100Signed : NonSemanticShaderDebugInfo100Unsigned)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(6); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - type->addIdOperand(nameId); // name id - type->addIdOperand(makeUintConstant(width)); // size id - if(hasSign == true) { - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Signed)); // encoding id - } else { - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Unsigned)); // encoding id - } - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeFloatDebugType(int const width) -{ - const char* typeName = nullptr; - switch (width) { - case 16: typeName = "float16_t"; break; - case 64: typeName = "double"; break; - default: typeName = "float"; break; - } - auto nameId = getStringId(typeName); - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == nameId && - type->getIdOperand(1) == static_cast(width) && - type->getIdOperand(2) == NonSemanticShaderDebugInfo100Float) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(6); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - type->addIdOperand(nameId); // name id - type->addIdOperand(makeUintConstant(width)); // size id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Float)); // encoding id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType) -{ - assert(sequenceType == NonSemanticShaderDebugInfo100DebugTypeArray || - sequenceType == NonSemanticShaderDebugInfo100DebugTypeVector); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[sequenceType].size(); ++t) { - type = groupedDebugTypes[sequenceType][t]; - if (type->getIdOperand(0) == baseType && - type->getIdOperand(1) == makeUintConstant(componentCount)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(4); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(sequenceType); - type->addIdOperand(debugId[baseType]); // base type - type->addIdOperand(componentCount); // component count - - groupedDebugTypes[sequenceType].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeArrayDebugType(Id const baseType, Id const componentCount) -{ - return makeSequentialDebugType(baseType, componentCount, NonSemanticShaderDebugInfo100DebugTypeArray); -} - -Id Builder::makeVectorDebugType(Id const baseType, int const componentCount) -{ - return makeSequentialDebugType(baseType, makeUintConstant(componentCount), NonSemanticShaderDebugInfo100DebugTypeVector); -} - -Id Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix][t]; - if (type->getIdOperand(0) == vectorType && - type->getIdOperand(1) == makeUintConstant(vectorCount)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(5); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMatrix); - type->addIdOperand(debugId[vectorType]); // vector type id - type->addIdOperand(makeUintConstant(vectorCount)); // component count id - type->addIdOperand(makeBoolConstant(columnMajor)); // column-major id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc) -{ - assert(debugId[memberType] != 0); - - Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(10); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember); - type->addIdOperand(getStringId(debugTypeLoc.name)); // name id - type->addIdOperand(debugId[memberType]); // type id - type->addIdOperand(makeDebugSource(currentFileId)); // source id - type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero - type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id - type->addIdOperand(makeUintConstant(0)); // TODO: offset id - type->addIdOperand(makeUintConstant(0)); // TODO: size id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMember].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -// Note: To represent a source language opaque type, this instruction must have no Members operands, Size operand must be -// DebugInfoNone, and Name must start with @ to avoid clashes with user defined names. -Id Builder::makeCompositeDebugType(std::vector const& memberTypes, char const*const name, - NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType) -{ - // Create the debug member types. - std::vector memberDebugTypes; - for(auto const memberType : memberTypes) { - assert(debugTypeLocs.find(memberType) != debugTypeLocs.end()); - - // There _should_ be debug types for all the member types but currently buffer references - // do not have member debug info generated. - if (debugId[memberType]) - memberDebugTypes.emplace_back(makeMemberDebugType(memberType, debugTypeLocs[memberType])); - - // TODO: Need to rethink this method of passing location information. - // debugTypeLocs.erase(memberType); - } - - // Create The structure debug type. - Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(memberDebugTypes.size() + 11); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite); - type->addIdOperand(getStringId(name)); // name id - type->addIdOperand(makeUintConstant(tag)); // tag id - type->addIdOperand(makeDebugSource(currentFileId)); // source id - type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? - type->addIdOperand(makeUintConstant(0)); // TODO: column id - type->addIdOperand(makeDebugCompilationUnit()); // scope id - if(isOpaqueType == true) { - // Prepend '@' to opaque types. - type->addIdOperand(getStringId('@' + std::string(name))); // linkage name id - type->addIdOperand(makeDebugInfoNone()); // size id - } else { - type->addIdOperand(getStringId(name)); // linkage name id - type->addIdOperand(makeUintConstant(0)); // TODO: size id - } - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id - assert(isOpaqueType == false || (isOpaqueType == true && memberDebugTypes.empty())); - for(auto const memberDebugType : memberDebugTypes) { - type->addIdOperand(memberDebugType); - } - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeComposite].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makePointerDebugType(StorageClass storageClass, Id const baseType) -{ - const Id debugBaseType = debugId[baseType]; - if (!debugBaseType) { - return makeDebugInfoNone(); - } - const Id scID = makeUintConstant(storageClass); - for (Instruction* otherType : groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypePointer]) { - if (otherType->getIdOperand(2) == debugBaseType && - otherType->getIdOperand(3) == scID) { - return otherType->getResultId(); - } - } - - Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->reserveOperands(5); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypePointer); - type->addIdOperand(debugBaseType); - type->addIdOperand(scID); - type->addIdOperand(makeUintConstant(0)); - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -// Emit a OpExtInstWithForwardRefsKHR nonsemantic instruction for a pointer debug type -// where we don't have the pointee yet. Since we don't have the pointee yet, it just -// points to itself and we rely on patching it later. -Id Builder::makeForwardPointerDebugType(StorageClass storageClass) -{ - const Id scID = makeUintConstant(storageClass); - - this->addExtension(spv::E_SPV_KHR_relaxed_extended_instruction); - - Instruction *type = new Instruction(getUniqueId(), makeVoidType(), OpExtInstWithForwardRefsKHR); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypePointer); - type->addIdOperand(type->getResultId()); - type->addIdOperand(scID); - type->addIdOperand(makeUintConstant(0)); - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeDebugSource(const Id fileName) { - if (debugSourceId.find(fileName) != debugSourceId.end()) - return debugSourceId[fileName]; - spv::Id resultId = getUniqueId(); - Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst); - sourceInst->reserveOperands(3); - sourceInst->addIdOperand(nonSemanticShaderDebugInfo); - sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugSource); - sourceInst->addIdOperand(fileName); - if (emitNonSemanticShaderDebugSource) { - spv::Id sourceId = 0; - if (fileName == mainFileId) { - sourceId = getStringId(sourceText); - } else { - auto incItr = includeFiles.find(fileName); - if (incItr != includeFiles.end()) { - sourceId = getStringId(*incItr->second); - } - } - - // We omit the optional source text item if not available in glslang - if (sourceId != 0) { - sourceInst->addIdOperand(sourceId); - } - } - constantsTypesGlobals.push_back(std::unique_ptr(sourceInst)); - module.mapInstruction(sourceInst); - debugSourceId[fileName] = resultId; - return resultId; -} - -Id Builder::makeDebugCompilationUnit() { - if (nonSemanticShaderCompilationUnitId != 0) - return nonSemanticShaderCompilationUnitId; - spv::Id resultId = getUniqueId(); - Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst); - sourceInst->reserveOperands(6); - sourceInst->addIdOperand(nonSemanticShaderDebugInfo); - sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit); - sourceInst->addIdOperand(makeUintConstant(1)); // TODO(greg-lunarg): Get rid of magic number - sourceInst->addIdOperand(makeUintConstant(4)); // TODO(greg-lunarg): Get rid of magic number - sourceInst->addIdOperand(makeDebugSource(mainFileId)); - sourceInst->addIdOperand(makeUintConstant(sourceLang)); - constantsTypesGlobals.push_back(std::unique_ptr(sourceInst)); - module.mapInstruction(sourceInst); - nonSemanticShaderCompilationUnitId = resultId; - - // We can reasonably assume that makeDebugCompilationUnit will be called before any of - // debug-scope stack. Function scopes and lexical scopes will occur afterward. - assert(currentDebugScopeId.empty()); - currentDebugScopeId.push(nonSemanticShaderCompilationUnitId); - - return resultId; -} - -Id Builder::createDebugGlobalVariable(Id const type, char const*const name, Id const variable) -{ - assert(type != 0); - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->reserveOperands(11); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable); - inst->addIdOperand(getStringId(name)); // name id - inst->addIdOperand(type); // type id - inst->addIdOperand(makeDebugSource(currentFileId)); // source id - inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? - inst->addIdOperand(makeUintConstant(0)); // TODO: column id - inst->addIdOperand(makeDebugCompilationUnit()); // scope id - inst->addIdOperand(getStringId(name)); // linkage name id - inst->addIdOperand(variable); // variable id - inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsDefinition)); // flags id - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - return inst->getResultId(); -} - -Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t const argNumber) -{ - assert(name != nullptr); - assert(!currentDebugScopeId.empty()); - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->reserveOperands(9); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable); - inst->addIdOperand(getStringId(name)); // name id - inst->addIdOperand(type); // type id - inst->addIdOperand(makeDebugSource(currentFileId)); // source id - inst->addIdOperand(makeUintConstant(currentLine)); // line id - inst->addIdOperand(makeUintConstant(0)); // TODO: column id - inst->addIdOperand(currentDebugScopeId.top()); // scope id - inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsLocal)); // flags id - if(argNumber != 0) { - inst->addIdOperand(makeUintConstant(argNumber)); - } - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - return inst->getResultId(); -} - -Id Builder::makeDebugExpression() -{ - if (debugExpression != 0) - return debugExpression; - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->reserveOperands(2); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugExpression); - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - debugExpression = inst->getResultId(); - - return debugExpression; -} - -Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const pointer) -{ - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->reserveOperands(5); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugDeclare); - inst->addIdOperand(debugLocalVariable); // debug local variable id - inst->addIdOperand(pointer); // pointer to local variable id - inst->addIdOperand(makeDebugExpression()); // expression id - addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -Id Builder::makeDebugValue(Id const debugLocalVariable, Id const value) -{ - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->reserveOperands(5); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugValue); - inst->addIdOperand(debugLocalVariable); // debug local variable id - inst->addIdOperand(value); // value of local variable id - inst->addIdOperand(makeDebugExpression()); // expression id - addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -Id Builder::makeAccelerationStructureType() -{ - Instruction *type; - if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR); - groupedTypes[OpTypeAccelerationStructureKHR].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - if (emitNonSemanticShaderDebugInfo) { - spv::Id debugType = makeCompositeDebugType({}, "accelerationStructure", NonSemanticShaderDebugInfo100Structure, true); - debugId[type->getResultId()] = debugType; - } - } else { - type = groupedTypes[OpTypeAccelerationStructureKHR].back(); - } - - return type->getResultId(); -} - -Id Builder::makeRayQueryType() -{ - Instruction *type; - if (groupedTypes[OpTypeRayQueryKHR].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryKHR); - groupedTypes[OpTypeRayQueryKHR].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - if (emitNonSemanticShaderDebugInfo) { - spv::Id debugType = makeCompositeDebugType({}, "rayQuery", NonSemanticShaderDebugInfo100Structure, true); - debugId[type->getResultId()] = debugType; - } - } else { - type = groupedTypes[OpTypeRayQueryKHR].back(); - } - - return type->getResultId(); -} - -Id Builder::makeHitObjectNVType() -{ - Instruction *type; - if (groupedTypes[OpTypeHitObjectNV].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeHitObjectNV); - groupedTypes[OpTypeHitObjectNV].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else { - type = groupedTypes[OpTypeHitObjectNV].back(); - } - - return type->getResultId(); -} - -Id Builder::getDerefTypeId(Id resultId) const -{ - Id typeId = getTypeId(resultId); - assert(isPointerType(typeId)); - - return module.getInstruction(typeId)->getIdOperand(1); -} - -Op Builder::getMostBasicTypeClass(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return getMostBasicTypeClass(instr->getIdOperand(0)); - case OpTypePointer: - return getMostBasicTypeClass(instr->getIdOperand(1)); - default: - return typeClass; - } -} - -unsigned int Builder::getNumTypeConstituents(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - switch (instr->getOpCode()) - { - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypePointer: - return 1; - case OpTypeVector: - case OpTypeMatrix: - return instr->getImmediateOperand(1); - case OpTypeArray: - { - Id lengthId = instr->getIdOperand(1); - return module.getInstruction(lengthId)->getImmediateOperand(0); - } - case OpTypeStruct: - return instr->getNumOperands(); - case OpTypeCooperativeMatrixKHR: - case OpTypeCooperativeMatrixNV: - // has only one constituent when used with OpCompositeConstruct. - return 1; - default: - assert(0); - return 1; - } -} - -// Return the lowest-level type of scalar that an homogeneous composite is made out of. -// Typically, this is just to find out if something is made out of ints or floats. -// However, it includes returning a structure, if say, it is an array of structure. -Id Builder::getScalarTypeId(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVoid: - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypeStruct: - return instr->getResultId(); - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - case OpTypePointer: - return getScalarTypeId(getContainedTypeId(typeId)); - default: - assert(0); - return NoResult; - } -} - -// Return the type of 'member' of a composite. -Id Builder::getContainedTypeId(Id typeId, int member) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - case OpTypeCooperativeMatrixKHR: - case OpTypeCooperativeMatrixNV: - return instr->getIdOperand(0); - case OpTypePointer: - return instr->getIdOperand(1); - case OpTypeStruct: - return instr->getIdOperand(member); - default: - assert(0); - return NoResult; - } -} - -// Figure out the final resulting type of the access chain. -Id Builder::getResultingAccessChainType() const -{ - assert(accessChain.base != NoResult); - Id typeId = getTypeId(accessChain.base); - - assert(isPointerType(typeId)); - typeId = getContainedTypeId(typeId); - - for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { - if (isStructType(typeId)) { - assert(isConstantScalar(accessChain.indexChain[i])); - typeId = getContainedTypeId(typeId, getConstantScalar(accessChain.indexChain[i])); - } else - typeId = getContainedTypeId(typeId, accessChain.indexChain[i]); - } - - return typeId; -} - -// Return the immediately contained type of a given composite type. -Id Builder::getContainedTypeId(Id typeId) const -{ - return getContainedTypeId(typeId, 0); -} - -// Returns true if 'typeId' is or contains a scalar type declared with 'typeOp' -// of width 'width'. The 'width' is only consumed for int and float types. -// Returns false otherwise. -bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const -{ - const Instruction& instr = *module.getInstruction(typeId); - - Op typeClass = instr.getOpCode(); - switch (typeClass) - { - case OpTypeInt: - case OpTypeFloat: - return typeClass == typeOp && instr.getImmediateOperand(0) == width; - case OpTypeStruct: - for (int m = 0; m < instr.getNumOperands(); ++m) { - if (containsType(instr.getIdOperand(m), typeOp, width)) - return true; - } - return false; - case OpTypePointer: - return false; - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return containsType(getContainedTypeId(typeId), typeOp, width); - default: - return typeClass == typeOp; - } -} - -// return true if the type is a pointer to PhysicalStorageBufferEXT or an -// contains such a pointer. These require restrict/aliased decorations. -bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const -{ - const Instruction& instr = *module.getInstruction(typeId); - - Op typeClass = instr.getOpCode(); - switch (typeClass) - { - case OpTypePointer: - return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT; - case OpTypeArray: - return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId)); - case OpTypeStruct: - for (int m = 0; m < instr.getNumOperands(); ++m) { - if (containsPhysicalStorageBufferOrArray(instr.getIdOperand(m))) - return true; - } - return false; - default: - return false; - } -} - -// See if a scalar constant of this type has already been created, so it -// can be reused rather than duplicated. (Required by the specification). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == value) - return constant->getResultId(); - } - - return 0; -} - -// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64'). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == v1 && - constant->getImmediateOperand(1) == v2) - return constant->getResultId(); - } - - return 0; -} - -// Return true if consuming 'opcode' means consuming a constant. -// "constant" here means after final transform to executable code, -// the value consumed will be a constant, so includes specialization. -bool Builder::isConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpUndef: - case OpConstantTrue: - case OpConstantFalse: - case OpConstant: - case OpConstantComposite: - case OpConstantCompositeReplicateEXT: - case OpConstantSampler: - case OpConstantNull: - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantCompositeReplicateEXT: - case OpSpecConstantOp: - return true; - default: - return false; - } -} - -// Return true if consuming 'opcode' means consuming a specialization constant. -bool Builder::isSpecConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantOp: - case OpSpecConstantCompositeReplicateEXT: - return true; - default: - return false; - } -} - -Id Builder::makeNullConstant(Id typeId) -{ - Instruction* constant; - - // See if we already made it. - Id existing = NoResult; - for (int i = 0; i < (int)nullConstants.size(); ++i) { - constant = nullConstants[i]; - if (constant->getTypeId() == typeId) - existing = constant->getResultId(); - } - - if (existing != NoResult) - return existing; - - // Make it - Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - nullConstants.push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeBoolConstant(bool b, bool specConstant) -{ - Id typeId = makeBoolType(); - Instruction* constant; - Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = 0; - for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) { - constant = groupedConstants[OpTypeBool][i]; - if (constant->getTypeId() == typeId && constant->getOpCode() == opcode) - existing = constant->getResultId(); - } - - if (existing) - return existing; - } - - // Make it - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeBool].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->reserveOperands(2); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFloatConstant(float f, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(32); - union { float fl; unsigned int ui; } u; - u.fl = f; - unsigned value = u.ui; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeDoubleConstant(double d, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(64); - union { double db; unsigned long long ull; } u; - u.db = d; - unsigned long long value = u.ull; - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->reserveOperands(2); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFloat16Constant(float f16, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(16); - - spvutils::HexFloat> fVal(f16); - spvutils::HexFloat> f16Val(0); - fVal.castTo(f16Val, spvutils::kRoundToZero); - - unsigned value = f16Val.value().getAsFloat().get_value(); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (!specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFpConstant(Id type, double d, bool specConstant) -{ - const int width = getScalarTypeWidth(type); - - assert(isFloatType(type)); - - switch (width) { - case 16: - return makeFloat16Constant((float)d, specConstant); - case 32: - return makeFloatConstant((float)d, specConstant); - case 64: - return makeDoubleConstant(d, specConstant); - default: - break; - } - - assert(false); - return NoResult; -} - -Id Builder::importNonSemanticShaderDebugInfoInstructions() -{ - assert(emitNonSemanticShaderDebugInfo == true); - - if(nonSemanticShaderDebugInfo == 0) - { - this->addExtension(spv::E_SPV_KHR_non_semantic_info); - nonSemanticShaderDebugInfo = this->import("NonSemantic.Shader.DebugInfo.100"); - } - - return nonSemanticShaderDebugInfo; -} - -Id Builder::findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps) -{ - Instruction* constant = nullptr; - bool found = false; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - - if (constant->getTypeId() != typeId) - continue; - - // same contents? - bool mismatch = false; - for (int op = 0; op < constant->getNumOperands(); ++op) { - if (constant->getIdOperand(op) != comps[op]) { - mismatch = true; - break; - } - } - if (! mismatch) { - found = true; - break; - } - } - - return found ? constant->getResultId() : NoResult; -} - -Id Builder::findStructConstant(Id typeId, const std::vector& comps) -{ - Instruction* constant = nullptr; - bool found = false; - for (int i = 0; i < (int)groupedStructConstants[typeId].size(); ++i) { - constant = groupedStructConstants[typeId][i]; - - // same contents? - bool mismatch = false; - for (int op = 0; op < constant->getNumOperands(); ++op) { - if (constant->getIdOperand(op) != comps[op]) { - mismatch = true; - break; - } - } - if (! mismatch) { - found = true; - break; - } - } - - return found ? constant->getResultId() : NoResult; -} - -// Comments in header -Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, bool specConstant) -{ - assert(typeId); - Op typeClass = getTypeClass(typeId); - - bool replicate = false; - size_t numMembers = members.size(); - if (useReplicatedComposites) { - // use replicate if all members are the same - replicate = numMembers > 0 && - std::equal(members.begin() + 1, members.end(), members.begin()); - - if (replicate) { - numMembers = 1; - addCapability(spv::CapabilityReplicatedCompositesEXT); - addExtension(spv::E_SPV_EXT_replicated_composites); - } - } - - Op opcode = replicate ? - (specConstant ? OpSpecConstantCompositeReplicateEXT : OpConstantCompositeReplicateEXT) : - (specConstant ? OpSpecConstantComposite : OpConstantComposite); - - switch (typeClass) { - case OpTypeVector: - case OpTypeArray: - case OpTypeMatrix: - case OpTypeCooperativeMatrixKHR: - case OpTypeCooperativeMatrixNV: - if (! specConstant) { - Id existing = findCompositeConstant(typeClass, typeId, members); - if (existing) - return existing; - } - break; - case OpTypeStruct: - if (! specConstant) { - Id existing = findStructConstant(typeId, members); - if (existing) - return existing; - } - break; - default: - assert(0); - return makeFloatConstant(0.0); - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->reserveOperands(members.size()); - for (size_t op = 0; op < numMembers; ++op) - c->addIdOperand(members[op]); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - if (typeClass == OpTypeStruct) - groupedStructConstants[typeId].push_back(c); - else - groupedConstants[typeClass].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name) -{ - Instruction* entryPoint = new Instruction(OpEntryPoint); - entryPoint->reserveOperands(3); - entryPoint->addImmediateOperand(model); - entryPoint->addIdOperand(function->getId()); - entryPoint->addStringOperand(name); - - entryPoints.push_back(std::unique_ptr(entryPoint)); - - return entryPoint; -} - -// Currently relying on the fact that all 'value' of interest are small non-negative values. -void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3) -{ - // entryPoint can be null if we are in compile-only mode - if (!entryPoint) - return; - - Instruction* instr = new Instruction(OpExecutionMode); - instr->reserveOperands(3); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - if (value1 >= 0) - instr->addImmediateOperand(value1); - if (value2 >= 0) - instr->addImmediateOperand(value2); - if (value3 >= 0) - instr->addImmediateOperand(value3); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector& literals) -{ - // entryPoint can be null if we are in compile-only mode - if (!entryPoint) - return; - - Instruction* instr = new Instruction(OpExecutionMode); - instr->reserveOperands(literals.size() + 2); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - for (auto literal : literals) - instr->addImmediateOperand(literal); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector& operandIds) -{ - // entryPoint can be null if we are in compile-only mode - if (!entryPoint) - return; - - Instruction* instr = new Instruction(OpExecutionModeId); - instr->reserveOperands(operandIds.size() + 2); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - for (auto operandId : operandIds) - instr->addIdOperand(operandId); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addName(Id id, const char* string) -{ - Instruction* name = new Instruction(OpName); - name->reserveOperands(2); - name->addIdOperand(id); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addMemberName(Id id, int memberNumber, const char* string) -{ - Instruction* name = new Instruction(OpMemberName); - name->reserveOperands(3); - name->addIdOperand(id); - name->addImmediateOperand(memberNumber); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addDecoration(Id id, Decoration decoration, int num) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorate); - dec->reserveOperands(2); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addDecoration(Id id, Decoration decoration, const char* s) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateString); - dec->reserveOperands(3); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - dec->addStringOperand(s); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addDecoration(Id id, Decoration decoration, const std::vector& literals) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorate); - dec->reserveOperands(literals.size() + 2); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - for (auto literal : literals) - dec->addImmediateOperand(literal); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addDecoration(Id id, Decoration decoration, const std::vector& strings) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateString); - dec->reserveOperands(strings.size() + 2); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - for (auto string : strings) - dec->addStringOperand(string); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType) { - Instruction* dec = new Instruction(OpDecorate); - dec->reserveOperands(4); - dec->addIdOperand(id); - dec->addImmediateOperand(spv::DecorationLinkageAttributes); - dec->addStringOperand(name); - dec->addImmediateOperand(linkType); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateId); - dec->reserveOperands(3); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - dec->addIdOperand(idDecoration); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addDecorationId(Id id, Decoration decoration, const std::vector& operandIds) -{ - if(decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateId); - dec->reserveOperands(operandIds.size() + 2); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - - for (auto operandId : operandIds) - dec->addIdOperand(operandId); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorate); - dec->reserveOperands(3); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorateStringGOOGLE); - dec->reserveOperands(4); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - dec->addStringOperand(s); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector& literals) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorate); - dec->reserveOperands(literals.size() + 3); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - for (auto literal : literals) - dec->addImmediateOperand(literal); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector& strings) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorateString); - dec->reserveOperands(strings.size() + 3); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - for (auto string : strings) - dec->addStringOperand(string); - - decorations.insert(std::unique_ptr(dec)); -} - -void Builder::addInstruction(std::unique_ptr inst) { - // Phis must appear first in their block, don't insert line tracking instructions - // in front of them, just add the OpPhi and return. - if (inst->getOpCode() == OpPhi) { - buildPoint->addInstruction(std::move(inst)); - return; - } - // Optionally insert OpDebugScope - if (emitNonSemanticShaderDebugInfo && dirtyScopeTracker) { - if (buildPoint->updateDebugScope(currentDebugScopeId.top())) { - auto scopeInst = std::make_unique(getUniqueId(), makeVoidType(), OpExtInst); - scopeInst->reserveOperands(3); - scopeInst->addIdOperand(nonSemanticShaderDebugInfo); - scopeInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugScope); - scopeInst->addIdOperand(currentDebugScopeId.top()); - buildPoint->addInstruction(std::move(scopeInst)); - } - - dirtyScopeTracker = false; - } - - // Insert OpLine/OpDebugLine if the debug source location has changed - if (trackDebugInfo && dirtyLineTracker) { - if (buildPoint->updateDebugSourceLocation(currentLine, 0, currentFileId)) { - if (emitSpirvDebugInfo) { - auto lineInst = std::make_unique(OpLine); - lineInst->reserveOperands(3); - lineInst->addIdOperand(currentFileId); - lineInst->addImmediateOperand(currentLine); - lineInst->addImmediateOperand(0); - buildPoint->addInstruction(std::move(lineInst)); - } - if (emitNonSemanticShaderDebugInfo) { - auto lineInst = std::make_unique(getUniqueId(), makeVoidType(), OpExtInst); - lineInst->reserveOperands(7); - lineInst->addIdOperand(nonSemanticShaderDebugInfo); - lineInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLine); - lineInst->addIdOperand(makeDebugSource(currentFileId)); - lineInst->addIdOperand(makeUintConstant(currentLine)); - lineInst->addIdOperand(makeUintConstant(currentLine)); - lineInst->addIdOperand(makeUintConstant(0)); - lineInst->addIdOperand(makeUintConstant(0)); - buildPoint->addInstruction(std::move(lineInst)); - } - } - - dirtyLineTracker = false; - } - - buildPoint->addInstruction(std::move(inst)); -} - -void Builder::addInstructionNoDebugInfo(std::unique_ptr inst) { - buildPoint->addInstruction(std::move(inst)); -} - -// Comments in header -Function* Builder::makeEntryPoint(const char* entryPoint) -{ - assert(! entryPointFunction); - - auto const returnType = makeVoidType(); - - restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo; - if(sourceLang == spv::SourceLanguageHLSL) { - emitNonSemanticShaderDebugInfo = false; - } - - Block* entry = nullptr; - entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, LinkageTypeMax, {}, {}, &entry); - - emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; - - return entryPointFunction; -} - -// Comments in header -Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, - const std::vector& paramTypes, - const std::vector>& decorations, Block** entry) -{ - // Make the function and initial instructions in it - Id typeId = makeFunctionType(returnType, paramTypes); - Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size()); - Id funcId = getUniqueId(); - Function* function = new Function(funcId, returnType, typeId, firstParamId, linkType, name, module); - - // Set up the precisions - setPrecision(function->getId(), precision); - function->setReturnPrecision(precision); - for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { - for (int d = 0; d < (int)decorations[p].size(); ++d) { - addDecoration(firstParamId + p, decorations[p][d]); - function->addParamPrecision(p, decorations[p][d]); - } - } - - // reset last debug scope - if (emitNonSemanticShaderDebugInfo) { - dirtyScopeTracker = true; - } - - // CFG - assert(entry != nullptr); - *entry = new Block(getUniqueId(), *function); - function->addBlock(*entry); - setBuildPoint(*entry); - - if (name) - addName(function->getId(), name); - - functions.push_back(std::unique_ptr(function)); - - return function; -} - -void Builder::setupFunctionDebugInfo(Function* function, const char* name, const std::vector& paramTypes, - const std::vector& paramNames) -{ - - if (!emitNonSemanticShaderDebugInfo) - return; - - Id nameId = getStringId(unmangleFunctionName(name)); - Id funcTypeId = function->getFuncTypeId(); - assert(debugId[funcTypeId] != 0); - Id funcId = function->getId(); - - assert(funcId != 0); - - // Make the debug function instruction - Id debugFuncId = makeDebugFunction(function, nameId, funcTypeId); - debugId[funcId] = debugFuncId; - currentDebugScopeId.push(debugFuncId); - - // DebugScope and DebugLine for parameter DebugDeclares - assert(paramTypes.size() == paramNames.size()); - if ((int)paramTypes.size() > 0) { - Id firstParamId = function->getParamId(0); - - for (size_t p = 0; p < paramTypes.size(); ++p) { - bool passByRef = false; - Id paramTypeId = paramTypes[p]; - - // For pointer-typed parameters, they are actually passed by reference and we need unwrap the pointer to get the actual parameter type. - if (isPointerType(paramTypeId) || isArrayType(paramTypeId)) { - passByRef = true; - paramTypeId = getContainedTypeId(paramTypeId); - } - - auto const& paramName = paramNames[p]; - auto const debugLocalVariableId = createDebugLocalVariable(debugId[paramTypeId], paramName, p + 1); - auto const paramId = static_cast(firstParamId + p); - debugId[paramId] = debugLocalVariableId; - - if (passByRef) { - makeDebugDeclare(debugLocalVariableId, paramId); - } else { - makeDebugValue(debugLocalVariableId, paramId); - } - } - } - - // Clear debug scope stack - if (emitNonSemanticShaderDebugInfo) - currentDebugScopeId.pop(); -} - -Id Builder::makeDebugFunction([[maybe_unused]] Function* function, Id nameId, Id funcTypeId) -{ - assert(function != nullptr); - assert(nameId != 0); - assert(funcTypeId != 0); - assert(debugId[funcTypeId] != 0); - - Id funcId = getUniqueId(); - auto type = new Instruction(funcId, makeVoidType(), OpExtInst); - type->reserveOperands(11); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunction); - type->addIdOperand(nameId); - type->addIdOperand(debugId[funcTypeId]); - type->addIdOperand(makeDebugSource(currentFileId)); // TODO: This points to file of definition instead of declaration - type->addIdOperand(makeUintConstant(currentLine)); // TODO: This points to line of definition instead of declaration - type->addIdOperand(makeUintConstant(0)); // column - type->addIdOperand(makeDebugCompilationUnit()); // scope - type->addIdOperand(nameId); // linkage name - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); - type->addIdOperand(makeUintConstant(currentLine)); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - return funcId; -} - -Id Builder::makeDebugLexicalBlock(uint32_t line, uint32_t column) { - assert(!currentDebugScopeId.empty()); - - Id lexId = getUniqueId(); - auto lex = new Instruction(lexId, makeVoidType(), OpExtInst); - lex->reserveOperands(6); - lex->addIdOperand(nonSemanticShaderDebugInfo); - lex->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLexicalBlock); - lex->addIdOperand(makeDebugSource(currentFileId)); - lex->addIdOperand(makeUintConstant(line)); - lex->addIdOperand(makeUintConstant(column)); // column - lex->addIdOperand(currentDebugScopeId.top()); // scope - constantsTypesGlobals.push_back(std::unique_ptr(lex)); - module.mapInstruction(lex); - return lexId; -} - -std::string Builder::unmangleFunctionName(std::string const& name) const -{ - assert(name.length() > 0); - - if(name.rfind('(') != std::string::npos) { - return name.substr(0, name.rfind('(')); - } else { - return name; - } -} - -// Comments in header -void Builder::makeReturn(bool implicit, Id retVal) -{ - if (retVal) { - Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue); - inst->addIdOperand(retVal); - addInstruction(std::unique_ptr(inst)); - } else - addInstruction(std::unique_ptr(new Instruction(NoResult, NoType, OpReturn))); - - if (! implicit) - createAndSetNoPredecessorBlock("post-return"); -} - -// Comments in header -void Builder::enterLexicalBlock(uint32_t line, uint32_t column) -{ - if (!emitNonSemanticShaderDebugInfo) { - return; - } - - // Generate new lexical scope debug instruction - Id lexId = makeDebugLexicalBlock(line, column); - currentDebugScopeId.push(lexId); - dirtyScopeTracker = true; -} - -// Comments in header -void Builder::leaveLexicalBlock() -{ - if (!emitNonSemanticShaderDebugInfo) { - return; - } - - // Pop current scope from stack and clear current scope - currentDebugScopeId.pop(); - dirtyScopeTracker = true; -} - -// Comments in header -void Builder::enterFunction(Function const* function) -{ - // Save and disable debugInfo for HLSL entry point function. It is a wrapper - // function with no user code in it. - restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo; - if (sourceLang == spv::SourceLanguageHLSL && function == entryPointFunction) { - emitNonSemanticShaderDebugInfo = false; - } - - if (emitNonSemanticShaderDebugInfo) { - // Initialize scope state - Id funcId = function->getFuncId(); - currentDebugScopeId.push(debugId[funcId]); - // Create DebugFunctionDefinition - spv::Id resultId = getUniqueId(); - Instruction* defInst = new Instruction(resultId, makeVoidType(), OpExtInst); - defInst->reserveOperands(4); - defInst->addIdOperand(nonSemanticShaderDebugInfo); - defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition); - defInst->addIdOperand(debugId[funcId]); - defInst->addIdOperand(funcId); - addInstruction(std::unique_ptr(defInst)); - } - - if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) { - Id funcId = function->getFuncId(); - addCapability(CapabilityLinkage); - addLinkageDecoration(funcId, function->getExportName(), linkType); - } -} - -// Comments in header -void Builder::leaveFunction() -{ - Block* block = buildPoint; - Function& function = buildPoint->getParent(); - assert(block); - - // If our function did not contain a return, add a return void now. - if (! block->isTerminated()) { - if (function.getReturnType() == makeVoidType()) - makeReturn(true); - else { - makeReturn(true, createUndefined(function.getReturnType())); - } - } - - // Clear function scope from debug scope stack - if (emitNonSemanticShaderDebugInfo) - currentDebugScopeId.pop(); - - emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; -} - -// Comments in header -void Builder::makeStatementTerminator(spv::Op opcode, const char *name) -{ - addInstruction(std::unique_ptr(new Instruction(opcode))); - createAndSetNoPredecessorBlock(name); -} - -// Comments in header -void Builder::makeStatementTerminator(spv::Op opcode, const std::vector& operands, const char* name) -{ - // It's assumed that the terminator instruction is always of void return type - // However in future if there is a need for non void return type, new helper - // methods can be created. - createNoResultOp(opcode, operands); - createAndSetNoPredecessorBlock(name); -} - -// Comments in header -Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer, - bool const compilerGenerated) -{ - Id pointerType = makePointer(storageClass, type); - Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable); - inst->addImmediateOperand(storageClass); - if (initializer != NoResult) - inst->addIdOperand(initializer); - - switch (storageClass) { - case StorageClassFunction: - // Validation rules require the declaration in the entry block - buildPoint->getParent().addLocalVariable(std::unique_ptr(inst)); - - if (emitNonSemanticShaderDebugInfo && !compilerGenerated) - { - auto const debugLocalVariableId = createDebugLocalVariable(debugId[type], name); - debugId[inst->getResultId()] = debugLocalVariableId; - - makeDebugDeclare(debugLocalVariableId, inst->getResultId()); - } - - break; - - default: - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = createDebugGlobalVariable(debugId[type], name, inst->getResultId()); - debugId[inst->getResultId()] = debugResultId; - } - break; - } - - if (name) - addName(inst->getResultId(), name); - setPrecision(inst->getResultId(), precision); - - return inst->getResultId(); -} - -// Comments in header -Id Builder::createUndefined(Id type) -{ - Instruction* inst = new Instruction(getUniqueId(), type, OpUndef); - addInstruction(std::unique_ptr(inst)); - return inst->getResultId(); -} - -// av/vis/nonprivate are unnecessary and illegal for some storage classes. -spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) - const -{ - switch (sc) { - case spv::StorageClassUniform: - case spv::StorageClassWorkgroup: - case spv::StorageClassStorageBuffer: - case spv::StorageClassPhysicalStorageBufferEXT: - break; - default: - memoryAccess = spv::MemoryAccessMask(memoryAccess & - ~(spv::MemoryAccessMakePointerAvailableKHRMask | - spv::MemoryAccessMakePointerVisibleKHRMask | - spv::MemoryAccessNonPrivatePointerKHRMask)); - break; - } - return memoryAccess; -} - -// Comments in header -void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, - unsigned int alignment) -{ - Instruction* store = new Instruction(OpStore); - store->reserveOperands(2); - store->addIdOperand(lValue); - store->addIdOperand(rValue); - - memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); - - if (memoryAccess != MemoryAccessMaskNone) { - store->addImmediateOperand(memoryAccess); - if (memoryAccess & spv::MemoryAccessAlignedMask) { - store->addImmediateOperand(alignment); - } - if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) { - store->addIdOperand(makeUintConstant(scope)); - } - } - - addInstruction(std::unique_ptr(store)); -} - -// Comments in header -Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess, - spv::Scope scope, unsigned int alignment) -{ - Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad); - load->addIdOperand(lValue); - - memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); - - if (memoryAccess != MemoryAccessMaskNone) { - load->addImmediateOperand(memoryAccess); - if (memoryAccess & spv::MemoryAccessAlignedMask) { - load->addImmediateOperand(alignment); - } - if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) { - load->addIdOperand(makeUintConstant(scope)); - } - } - - addInstruction(std::unique_ptr(load)); - setPrecision(load->getResultId(), precision); - - return load->getResultId(); -} - -// Comments in header -Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector& offsets) -{ - // Figure out the final resulting type. - Id typeId = getResultingAccessChainType(); - typeId = makePointer(storageClass, typeId); - - // Make the instruction - Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain); - chain->reserveOperands(offsets.size() + 1); - chain->addIdOperand(base); - for (int i = 0; i < (int)offsets.size(); ++i) - chain->addIdOperand(offsets[i]); - addInstruction(std::unique_ptr(chain)); - - return chain->getResultId(); -} - -Id Builder::createArrayLength(Id base, unsigned int member) -{ - spv::Id intType = makeUintType(32); - Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength); - length->reserveOperands(2); - length->addIdOperand(base); - length->addImmediateOperand(member); - addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCooperativeMatrixLengthKHR(Id type) -{ - spv::Id intType = makeUintType(32); - - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCooperativeMatrixLengthKHR, intType, std::vector(1, type), std::vector()); - } - - Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthKHR); - length->addIdOperand(type); - addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCooperativeMatrixLengthNV(Id type) -{ - spv::Id intType = makeUintType(32); - - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCooperativeMatrixLengthNV, intType, std::vector(1, type), std::vector()); - } - - Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV); - length->addIdOperand(type); - addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), - std::vector(1, index)); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->reserveOperands(2); - extract->addIdOperand(composite); - extract->addImmediateOperand(index); - addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector& indexes) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), indexes); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->reserveOperands(indexes.size() + 1); - extract->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - extract->addImmediateOperand(indexes[i]); - addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->reserveOperands(3); - insert->addIdOperand(object); - insert->addIdOperand(composite); - insert->addImmediateOperand(index); - addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->reserveOperands(indexes.size() + 2); - insert->addIdOperand(object); - insert->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - insert->addImmediateOperand(indexes[i]); - addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex) -{ - Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic); - extract->reserveOperands(2); - extract->addIdOperand(vector); - extract->addIdOperand(componentIndex); - addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic); - insert->reserveOperands(3); - insert->addIdOperand(vector); - insert->addIdOperand(component); - insert->addIdOperand(componentIndex); - addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -// An opcode that has no operands, no result id, and no type -void Builder::createNoResultOp(Op opCode) -{ - Instruction* op = new Instruction(opCode); - addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one id operand, no result id, and no type -void Builder::createNoResultOp(Op opCode, Id operand) -{ - Instruction* op = new Instruction(opCode); - op->addIdOperand(operand); - addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one or more operands, no result id, and no type -void Builder::createNoResultOp(Op opCode, const std::vector& operands) -{ - Instruction* op = new Instruction(opCode); - op->reserveOperands(operands.size()); - for (auto id : operands) { - op->addIdOperand(id); - } - addInstruction(std::unique_ptr(op)); -} - -// An opcode that has multiple operands, no result id, and no type -void Builder::createNoResultOp(Op opCode, const std::vector& operands) -{ - Instruction* op = new Instruction(opCode); - op->reserveOperands(operands.size()); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) { - if (it->isId) - op->addIdOperand(it->word); - else - op->addImmediateOperand(it->word); - } - addInstruction(std::unique_ptr(op)); -} - -void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics) -{ - Instruction* op = new Instruction(OpControlBarrier); - op->reserveOperands(3); - op->addIdOperand(makeUintConstant(execution)); - op->addIdOperand(makeUintConstant(memory)); - op->addIdOperand(makeUintConstant(semantics)); - addInstruction(std::unique_ptr(op)); -} - -void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics) -{ - Instruction* op = new Instruction(OpMemoryBarrier); - op->reserveOperands(2); - op->addIdOperand(makeUintConstant(executionScope)); - op->addIdOperand(makeUintConstant(memorySemantics)); - addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operands, a result id, and a type -Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(opCode, typeId, std::vector(1, operand), std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(operand); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = left; operands[1] = right; - return createSpecConstantOp(opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->reserveOperands(2); - op->addIdOperand(left); - op->addIdOperand(right); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(3); - operands[0] = op1; - operands[1] = op2; - operands[2] = op3; - return createSpecConstantOp( - opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->reserveOperands(3); - op->addIdOperand(op1); - op->addIdOperand(op2); - op->addIdOperand(op3); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->reserveOperands(operands.size()); - for (auto id : operands) - op->addIdOperand(id); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->reserveOperands(operands.size()); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) { - if (it->isId) - op->addIdOperand(it->word); - else - op->addImmediateOperand(it->word); - } - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, - const std::vector& literals) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); - op->reserveOperands(operands.size() + literals.size() + 1); - op->addImmediateOperand((unsigned) opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - for (auto it = literals.cbegin(); it != literals.cend(); ++it) - op->addImmediateOperand(*it); - module.mapInstruction(op); - constantsTypesGlobals.push_back(std::unique_ptr(op)); - - // OpSpecConstantOp's using 8 or 16 bit types require the associated capability - if (containsType(typeId, OpTypeInt, 8)) - addCapability(CapabilityInt8); - if (containsType(typeId, OpTypeInt, 16)) - addCapability(CapabilityInt16); - if (containsType(typeId, OpTypeFloat, 16)) - addCapability(CapabilityFloat16); - - return op->getResultId(); -} - -Id Builder::createFunctionCall(spv::Function* function, const std::vector& args) -{ - Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); - op->reserveOperands(args.size() + 1); - op->addIdOperand(function->getId()); - for (int a = 0; a < (int)args.size(); ++a) - op->addIdOperand(args[a]); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Comments in header -Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels) -{ - if (channels.size() == 1) - return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); - - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = operands[1] = source; - return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision); - } - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - assert(isVector(source)); - swizzle->reserveOperands(channels.size() + 2); - swizzle->addIdOperand(source); - swizzle->addIdOperand(source); - for (int i = 0; i < (int)channels.size(); ++i) - swizzle->addImmediateOperand(channels[i]); - addInstruction(std::unique_ptr(swizzle)); - - return setPrecision(swizzle->getResultId(), precision); -} - -// Comments in header -Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels) -{ - if (channels.size() == 1 && getNumComponents(source) == 1) - return createCompositeInsert(source, target, typeId, channels.front()); - - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - - assert(isVector(target)); - swizzle->reserveOperands(2); - swizzle->addIdOperand(target); - - assert(getNumComponents(source) == channels.size()); - assert(isVector(source)); - swizzle->addIdOperand(source); - - // Set up an identity shuffle from the base value to the result value - unsigned int components[4]; - int numTargetComponents = getNumComponents(target); - for (int i = 0; i < numTargetComponents; ++i) - components[i] = i; - - // Punch in the l-value swizzle - for (int i = 0; i < (int)channels.size(); ++i) - components[channels[i]] = numTargetComponents + i; - - // finish the instruction with these components selectors - swizzle->reserveOperands(numTargetComponents); - for (int i = 0; i < numTargetComponents; ++i) - swizzle->addImmediateOperand(components[i]); - addInstruction(std::unique_ptr(swizzle)); - - return swizzle->getResultId(); -} - -// Comments in header -void Builder::promoteScalar(Decoration precision, Id& left, Id& right) -{ - int direction = getNumComponents(right) - getNumComponents(left); - - if (direction > 0) - left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right))); - else if (direction < 0) - right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left))); - - return; -} - -// Comments in header -Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) -{ - assert(getNumComponents(scalar) == 1); - assert(getTypeId(scalar) == getScalarTypeId(vectorType)); - - int numComponents = getNumTypeComponents(vectorType); - if (numComponents == 1) - return scalar; - - Instruction* smear = nullptr; - if (generatingOpCodeForSpecConst) { - auto members = std::vector(numComponents, scalar); - // Sometime even in spec-constant-op mode, the temporary vector created by - // promoting a scalar might not be a spec constant. This should depend on - // the scalar. - // e.g.: - // const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar; - // In such cases, the temporary vector created from a_front_end_const_scalar - // is not a spec constant vector, even though the binary operation node is marked - // as 'specConstant' and we are in spec-constant-op mode. - auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar)); - smear = module.getInstruction(result_id); - } else { - bool replicate = useReplicatedComposites && (numComponents > 0); - - if (replicate) { - numComponents = 1; - addCapability(spv::CapabilityReplicatedCompositesEXT); - addExtension(spv::E_SPV_EXT_replicated_composites); - } - - Op opcode = replicate ? OpCompositeConstructReplicateEXT : OpCompositeConstruct; - - smear = new Instruction(getUniqueId(), vectorType, opcode); - smear->reserveOperands(numComponents); - for (int c = 0; c < numComponents; ++c) - smear->addIdOperand(scalar); - addInstruction(std::unique_ptr(smear)); - } - - return setPrecision(smear->getResultId(), precision); -} - -// Comments in header -Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args) -{ - Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst); - inst->reserveOperands(args.size() + 2); - inst->addIdOperand(builtins); - inst->addImmediateOperand(entryPoint); - for (int arg = 0; arg < (int)args.size(); ++arg) - inst->addIdOperand(args[arg]); - - addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -// Accept all parameters needed to create a texture instruction. -// Create the correct instruction based on the inputs, and make the call. -Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, - bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask) -{ - std::vector texArgs; - - // - // Set up the fixed arguments - // - bool explicitLod = false; - texArgs.push_back(parameters.sampler); - texArgs.push_back(parameters.coords); - if (parameters.Dref != NoResult) - texArgs.push_back(parameters.Dref); - if (parameters.component != NoResult) - texArgs.push_back(parameters.component); - - if (parameters.granularity != NoResult) - texArgs.push_back(parameters.granularity); - if (parameters.coarse != NoResult) - texArgs.push_back(parameters.coarse); - - // - // Set up the optional arguments - // - size_t optArgNum = texArgs.size(); // the position of the mask for the optional arguments, if any. - ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand - if (parameters.bias) { - mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask); - texArgs.push_back(parameters.bias); - } - if (parameters.lod) { - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs.push_back(parameters.lod); - explicitLod = true; - } else if (parameters.gradX) { - mask = (ImageOperandsMask)(mask | ImageOperandsGradMask); - texArgs.push_back(parameters.gradX); - texArgs.push_back(parameters.gradY); - explicitLod = true; - } else if (noImplicitLod && ! fetch && ! gather) { - // have to explicitly use lod of 0 if not allowed to have them be implicit, and - // we would otherwise be about to issue an implicit instruction - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs.push_back(makeFloatConstant(0.0)); - explicitLod = true; - } - if (parameters.offset) { - if (isConstant(parameters.offset)) - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask); - else { - addCapability(CapabilityImageGatherExtended); - mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask); - } - texArgs.push_back(parameters.offset); - } - if (parameters.offsets) { - addCapability(CapabilityImageGatherExtended); - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask); - texArgs.push_back(parameters.offsets); - } - if (parameters.sample) { - mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask); - texArgs.push_back(parameters.sample); - } - if (parameters.lodClamp) { - // capability if this bit is used - addCapability(CapabilityMinLod); - - mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask); - texArgs.push_back(parameters.lodClamp); - } - if (parameters.nonprivate) { - mask = mask | ImageOperandsNonPrivateTexelKHRMask; - } - if (parameters.volatil) { - mask = mask | ImageOperandsVolatileTexelKHRMask; - } - mask = mask | signExtensionMask; - // insert the operand for the mask, if any bits were set. - if (mask != ImageOperandsMaskNone) - texArgs.insert(texArgs.begin() + optArgNum, mask); - - // - // Set up the instruction - // - Op opCode = OpNop; // All paths below need to set this - if (fetch) { - if (sparse) - opCode = OpImageSparseFetch; - else - opCode = OpImageFetch; - } else if (parameters.granularity && parameters.coarse) { - opCode = OpImageSampleFootprintNV; - } else if (gather) { - if (parameters.Dref) - if (sparse) - opCode = OpImageSparseDrefGather; - else - opCode = OpImageDrefGather; - else - if (sparse) - opCode = OpImageSparseGather; - else - opCode = OpImageGather; - } else if (explicitLod) { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefExplicitLod; - else - opCode = OpImageSampleProjDrefExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefExplicitLod; - else - opCode = OpImageSampleDrefExplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjExplicitLod; - else - opCode = OpImageSampleProjExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleExplicitLod; - else - opCode = OpImageSampleExplicitLod; - } - } else { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefImplicitLod; - else - opCode = OpImageSampleProjDrefImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefImplicitLod; - else - opCode = OpImageSampleDrefImplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjImplicitLod; - else - opCode = OpImageSampleProjImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleImplicitLod; - else - opCode = OpImageSampleImplicitLod; - } - } - - // See if the result type is expecting a smeared result. - // This happens when a legacy shadow*() call is made, which - // gets a vec4 back instead of a float. - Id smearedType = resultType; - if (! isScalarType(resultType)) { - switch (opCode) { - case OpImageSampleDrefImplicitLod: - case OpImageSampleDrefExplicitLod: - case OpImageSampleProjDrefImplicitLod: - case OpImageSampleProjDrefExplicitLod: - resultType = getScalarTypeId(resultType); - break; - default: - break; - } - } - - Id typeId0 = 0; - Id typeId1 = 0; - - if (sparse) { - typeId0 = resultType; - typeId1 = getDerefTypeId(parameters.texelOut); - resultType = makeStructResultType(typeId0, typeId1); - } - - // Build the SPIR-V instruction - Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode); - textureInst->reserveOperands(optArgNum + (texArgs.size() - (optArgNum + 1))); - for (size_t op = 0; op < optArgNum; ++op) - textureInst->addIdOperand(texArgs[op]); - if (optArgNum < texArgs.size()) - textureInst->addImmediateOperand(texArgs[optArgNum]); - for (size_t op = optArgNum + 1; op < texArgs.size(); ++op) - textureInst->addIdOperand(texArgs[op]); - setPrecision(textureInst->getResultId(), precision); - addInstruction(std::unique_ptr(textureInst)); - - Id resultId = textureInst->getResultId(); - - if (sparse) { - // set capability - addCapability(CapabilitySparseResidency); - - // Decode the return type that was a special structure - createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut); - resultId = createCompositeExtract(resultId, typeId0, 0); - setPrecision(resultId, precision); - } else { - // When a smear is needed, do it, as per what was computed - // above when resultType was changed to a scalar type. - if (resultType != smearedType) - resultId = smearScalar(precision, resultId, smearedType); - } - - return resultId; -} - -// Comments in header -Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult) -{ - // Figure out the result type - Id resultType = 0; - switch (opCode) { - case OpImageQuerySize: - case OpImageQuerySizeLod: - { - int numComponents = 0; - switch (getTypeDimensionality(getImageType(parameters.sampler))) { - case Dim1D: - case DimBuffer: - numComponents = 1; - break; - case Dim2D: - case DimCube: - case DimRect: - case DimSubpassData: - numComponents = 2; - break; - case Dim3D: - numComponents = 3; - break; - - default: - assert(0); - break; - } - if (isArrayedImageType(getImageType(parameters.sampler))) - ++numComponents; - - Id intType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - if (numComponents == 1) - resultType = intType; - else - resultType = makeVectorType(intType, numComponents); - - break; - } - case OpImageQueryLod: - resultType = makeVectorType(getScalarTypeId(getTypeId(parameters.coords)), 2); - break; - case OpImageQueryLevels: - case OpImageQuerySamples: - resultType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - break; - default: - assert(0); - break; - } - - Instruction* query = new Instruction(getUniqueId(), resultType, opCode); - query->addIdOperand(parameters.sampler); - if (parameters.coords) - query->addIdOperand(parameters.coords); - if (parameters.lod) - query->addIdOperand(parameters.lod); - addInstruction(std::unique_ptr(query)); - addCapability(CapabilityImageQuery); - - return query->getResultId(); -} - -// External comments in header. -// Operates recursively to visit the composite's hierarchy. -Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal) -{ - Id boolType = makeBoolType(); - Id valueType = getTypeId(value1); - - Id resultId = NoResult; - - int numConstituents = getNumTypeConstituents(valueType); - - // Scalars and Vectors - - if (isScalarType(valueType) || isVectorType(valueType)) { - assert(valueType == getTypeId(value2)); - // These just need a single comparison, just have - // to figure out what it is. - Op op; - switch (getMostBasicTypeClass(valueType)) { - case OpTypeFloat: - op = equal ? OpFOrdEqual : OpFUnordNotEqual; - break; - case OpTypeInt: - default: - op = equal ? OpIEqual : OpINotEqual; - break; - case OpTypeBool: - op = equal ? OpLogicalEqual : OpLogicalNotEqual; - precision = NoPrecision; - break; - } - - if (isScalarType(valueType)) { - // scalar - resultId = createBinOp(op, boolType, value1, value2); - } else { - // vector - resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2); - setPrecision(resultId, precision); - // reduce vector compares... - resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId); - } - - return setPrecision(resultId, precision); - } - - // Only structs, arrays, and matrices should be left. - // They share in common the reduction operation across their constituents. - assert(isAggregateType(valueType) || isMatrixType(valueType)); - - // Compare each pair of constituents - for (int constituent = 0; constituent < numConstituents; ++constituent) { - std::vector indexes(1, constituent); - Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent); - Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent); - Id constituent1 = createCompositeExtract(value1, constituentType1, indexes); - Id constituent2 = createCompositeExtract(value2, constituentType2, indexes); - - Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal); - - if (constituent == 0) - resultId = subResultId; - else - resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), - precision); - } - - return resultId; -} - -// OpCompositeConstruct -Id Builder::createCompositeConstruct(Id typeId, const std::vector& constituents) -{ - assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && - getNumTypeConstituents(typeId) == constituents.size())); - - if (generatingOpCodeForSpecConst) { - // Sometime, even in spec-constant-op mode, the constant composite to be - // constructed may not be a specialization constant. - // e.g.: - // const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const); - // The first column vector should be a spec constant one, as a_spec_const is a spec constant. - // The second column vector should NOT be spec constant, as it does not contain any spec constants. - // To handle such cases, we check the constituents of the constant vector to determine whether this - // vector should be created as a spec constant. - return makeCompositeConstant(typeId, constituents, - std::any_of(constituents.begin(), constituents.end(), - [&](spv::Id id) { return isSpecConstant(id); })); - } - - bool replicate = false; - size_t numConstituents = constituents.size(); - - if (useReplicatedComposites) { - replicate = numConstituents > 0 && - std::equal(constituents.begin() + 1, constituents.end(), constituents.begin()); - } - - if (replicate) { - numConstituents = 1; - addCapability(spv::CapabilityReplicatedCompositesEXT); - addExtension(spv::E_SPV_EXT_replicated_composites); - } - - Op opcode = replicate ? OpCompositeConstructReplicateEXT : OpCompositeConstruct; - - Instruction* op = new Instruction(getUniqueId(), typeId, opcode); - op->reserveOperands(constituents.size()); - for (size_t c = 0; c < numConstituents; ++c) - op->addIdOperand(constituents[c]); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// coopmat conversion -Id Builder::createCooperativeMatrixConversion(Id typeId, Id source) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, OpCooperativeMatrixConvertNV); - op->addIdOperand(source); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// coopmat reduce -Id Builder::createCooperativeMatrixReduce(Op opcode, Id typeId, Id source, unsigned int mask, Id func) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, opcode); - op->addIdOperand(source); - op->addImmediateOperand(mask); - op->addIdOperand(func); - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// coopmat per-element operation -Id Builder::createCooperativeMatrixPerElementOp(Id typeId, const std::vector& operands) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, spv::OpCooperativeMatrixPerElementOpNV); - // skip operand[0], which is where the result is stored - for (uint32_t i = 1; i < operands.size(); ++i) { - op->addIdOperand(operands[i]); - } - addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Vector or scalar constructor -Id Builder::createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id result = NoResult; - unsigned int numTargetComponents = getNumTypeComponents(resultTypeId); - unsigned int targetComponent = 0; - - // Special case: when calling a vector constructor with a single scalar - // argument, smear the scalar - if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1) - return smearScalar(precision, sources[0], resultTypeId); - - // Special case: 2 vectors of equal size - if (sources.size() == 1 && isVector(sources[0]) && numTargetComponents == getNumComponents(sources[0])) { - assert(resultTypeId == getTypeId(sources[0])); - return sources[0]; - } - - // accumulate the arguments for OpCompositeConstruct - std::vector constituents; - Id scalarTypeId = getScalarTypeId(resultTypeId); - - // lambda to store the result of visiting an argument component - const auto latchResult = [&](Id comp) { - if (numTargetComponents > 1) - constituents.push_back(comp); - else - result = comp; - ++targetComponent; - }; - - // lambda to visit a vector argument's components - const auto accumulateVectorConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumComponents(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - for (unsigned int s = 0; s < sourcesToUse; ++s) { - std::vector swiz; - swiz.push_back(s); - latchResult(createRvalueSwizzle(precision, scalarTypeId, sourceArg, swiz)); - } - }; - - // lambda to visit a matrix argument's components - const auto accumulateMatrixConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumColumns(sourceArg) * getNumRows(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - unsigned int col = 0; - unsigned int row = 0; - for (unsigned int s = 0; s < sourcesToUse; ++s) { - if (row >= getNumRows(sourceArg)) { - row = 0; - col++; - } - std::vector indexes; - indexes.push_back(col); - indexes.push_back(row); - latchResult(createCompositeExtract(sourceArg, scalarTypeId, indexes)); - row++; - } - }; - - // Go through the source arguments, each one could have either - // a single or multiple components to contribute. - for (unsigned int i = 0; i < sources.size(); ++i) { - - if (isScalar(sources[i]) || isPointer(sources[i])) - latchResult(sources[i]); - else if (isVector(sources[i])) - accumulateVectorConstituents(sources[i]); - else if (isMatrix(sources[i])) - accumulateMatrixConstituents(sources[i]); - else - assert(0); - - if (targetComponent >= numTargetComponents) - break; - } - - // If the result is a vector, make it from the gathered constituents. - if (constituents.size() > 0) { - result = createCompositeConstruct(resultTypeId, constituents); - return setPrecision(result, precision); - } else { - // Precision was set when generating this component. - return result; - } -} - -// Comments in header -Id Builder::createMatrixConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id componentTypeId = getScalarTypeId(resultTypeId); - unsigned int numCols = getTypeNumColumns(resultTypeId); - unsigned int numRows = getTypeNumRows(resultTypeId); - - Instruction* instr = module.getInstruction(componentTypeId); - const unsigned bitCount = instr->getImmediateOperand(0); - - // Optimize matrix constructed from a bigger matrix - if (isMatrix(sources[0]) && getNumColumns(sources[0]) >= numCols && getNumRows(sources[0]) >= numRows) { - // To truncate the matrix to a smaller number of rows/columns, we need to: - // 1. For each column, extract the column and truncate it to the required size using shuffle - // 2. Assemble the resulting matrix from all columns - Id matrix = sources[0]; - Id columnTypeId = getContainedTypeId(resultTypeId); - Id sourceColumnTypeId = getContainedTypeId(getTypeId(matrix)); - - std::vector channels; - for (unsigned int row = 0; row < numRows; ++row) - channels.push_back(row); - - std::vector matrixColumns; - for (unsigned int col = 0; col < numCols; ++col) { - std::vector indexes; - indexes.push_back(col); - Id colv = createCompositeExtract(matrix, sourceColumnTypeId, indexes); - setPrecision(colv, precision); - - if (numRows != getNumRows(matrix)) { - matrixColumns.push_back(createRvalueSwizzle(precision, columnTypeId, colv, channels)); - } else { - matrixColumns.push_back(colv); - } - } - - return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); - } - - // Detect a matrix being constructed from a repeated vector of the correct size. - // Create the composite directly from it. - if (sources.size() == numCols && isVector(sources[0]) && getNumComponents(sources[0]) == numRows && - std::equal(sources.begin() + 1, sources.end(), sources.begin())) { - return setPrecision(createCompositeConstruct(resultTypeId, sources), precision); - } - - // Otherwise, will use a two step process - // 1. make a compile-time 2D array of values - // 2. construct a matrix from that array - - // Step 1. - - // initialize the array to the identity matrix - Id ids[maxMatrixSize][maxMatrixSize]; - Id one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0)); - Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0)); - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 4; ++row) { - if (col == row) - ids[col][row] = one; - else - ids[col][row] = zero; - } - } - - // modify components as dictated by the arguments - if (sources.size() == 1 && isScalar(sources[0])) { - // a single scalar; resets the diagonals - for (int col = 0; col < 4; ++col) - ids[col][col] = sources[0]; - } else if (isMatrix(sources[0])) { - // constructing from another matrix; copy over the parts that exist in both the argument and constructee - Id matrix = sources[0]; - unsigned int minCols = std::min(numCols, getNumColumns(matrix)); - unsigned int minRows = std::min(numRows, getNumRows(matrix)); - for (unsigned int col = 0; col < minCols; ++col) { - std::vector indexes; - indexes.push_back(col); - for (unsigned int row = 0; row < minRows; ++row) { - indexes.push_back(row); - ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes); - indexes.pop_back(); - setPrecision(ids[col][row], precision); - } - } - } else { - // fill in the matrix in column-major order with whatever argument components are available - unsigned int row = 0; - unsigned int col = 0; - - for (unsigned int arg = 0; arg < sources.size() && col < numCols; ++arg) { - Id argComp = sources[arg]; - for (unsigned int comp = 0; comp < getNumComponents(sources[arg]); ++comp) { - if (getNumComponents(sources[arg]) > 1) { - argComp = createCompositeExtract(sources[arg], componentTypeId, comp); - setPrecision(argComp, precision); - } - ids[col][row++] = argComp; - if (row == numRows) { - row = 0; - col++; - } - if (col == numCols) { - // If more components are provided than fit the matrix, discard the rest. - break; - } - } - } - } - - // Step 2: Construct a matrix from that array. - // First make the column vectors, then make the matrix. - - // make the column vectors - Id columnTypeId = getContainedTypeId(resultTypeId); - std::vector matrixColumns; - for (unsigned int col = 0; col < numCols; ++col) { - std::vector vectorComponents; - for (unsigned int row = 0; row < numRows; ++row) - vectorComponents.push_back(ids[col][row]); - Id column = createCompositeConstruct(columnTypeId, vectorComponents); - setPrecision(column, precision); - matrixColumns.push_back(column); - } - - // make the matrix - return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); -} - -// Comments in header -Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) : - builder(gb), - condition(cond), - control(ctrl), - elseBlock(nullptr) -{ - function = &builder.getBuildPoint()->getParent(); - - // make the blocks, but only put the then-block into the function, - // the else-block and merge-block will be added later, in order, after - // earlier code is emitted - thenBlock = new Block(builder.getUniqueId(), *function); - mergeBlock = new Block(builder.getUniqueId(), *function); - - // Save the current block, so that we can add in the flow control split when - // makeEndIf is called. - headerBlock = builder.getBuildPoint(); - builder.createSelectionMerge(mergeBlock, control); - - function->addBlock(thenBlock); - builder.setBuildPoint(thenBlock); -} - -// Comments in header -void Builder::If::makeBeginElse() -{ - // Close out the "then" by having it jump to the mergeBlock - builder.createBranch(true, mergeBlock); - - // Make the first else block and add it to the function - elseBlock = new Block(builder.getUniqueId(), *function); - function->addBlock(elseBlock); - - // Start building the else block - builder.setBuildPoint(elseBlock); -} - -// Comments in header -void Builder::If::makeEndIf() -{ - // jump to the merge block - builder.createBranch(true, mergeBlock); - - // Go back to the headerBlock and make the flow control split - builder.setBuildPoint(headerBlock); - if (elseBlock) - builder.createConditionalBranch(condition, thenBlock, elseBlock); - else - builder.createConditionalBranch(condition, thenBlock, mergeBlock); - - // add the merge block to the function - function->addBlock(mergeBlock); - builder.setBuildPoint(mergeBlock); -} - -// Comments in header -void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueIndexToSegment, int defaultSegment, - std::vector& segmentBlocks) -{ - Function& function = buildPoint->getParent(); - - // make all the blocks - for (int s = 0; s < numSegments; ++s) - segmentBlocks.push_back(new Block(getUniqueId(), function)); - - Block* mergeBlock = new Block(getUniqueId(), function); - - // make and insert the switch's selection-merge instruction - createSelectionMerge(mergeBlock, control); - - // make the switch instruction - Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch); - switchInst->reserveOperands((caseValues.size() * 2) + 2); - switchInst->addIdOperand(selector); - auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock; - switchInst->addIdOperand(defaultOrMerge->getId()); - defaultOrMerge->addPredecessor(buildPoint); - for (int i = 0; i < (int)caseValues.size(); ++i) { - switchInst->addImmediateOperand(caseValues[i]); - switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId()); - segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint); - } - addInstruction(std::unique_ptr(switchInst)); - - // push the merge block - switchMerges.push(mergeBlock); -} - -// Comments in header -void Builder::addSwitchBreak(bool implicit) -{ - // branch to the top of the merge block stack - createBranch(implicit, switchMerges.top()); - createAndSetNoPredecessorBlock("post-switch-break"); -} - -// Comments in header -void Builder::nextSwitchSegment(std::vector& segmentBlock, int nextSegment) -{ - int lastSegment = nextSegment - 1; - if (lastSegment >= 0) { - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - createBranch(true, segmentBlock[nextSegment]); - } - Block* block = segmentBlock[nextSegment]; - block->getParent().addBlock(block); - setBuildPoint(block); -} - -// Comments in header -void Builder::endSwitch(std::vector& /*segmentBlock*/) -{ - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - addSwitchBreak(true); - - switchMerges.top()->getParent().addBlock(switchMerges.top()); - setBuildPoint(switchMerges.top()); - - switchMerges.pop(); -} - -Block& Builder::makeNewBlock() -{ - Function& function = buildPoint->getParent(); - auto block = new Block(getUniqueId(), function); - function.addBlock(block); - return *block; -} - -Builder::LoopBlocks& Builder::makeNewLoop() -{ - // This verbosity is needed to simultaneously get the same behavior - // everywhere (id's in the same order), have a syntax that works - // across lots of versions of C++, have no warnings from pedantic - // compilation modes, and leave the rest of the code alone. - Block& head = makeNewBlock(); - Block& body = makeNewBlock(); - Block& merge = makeNewBlock(); - Block& continue_target = makeNewBlock(); - LoopBlocks blocks(head, body, merge, continue_target); - loops.push(blocks); - return loops.top(); -} - -void Builder::createLoopContinue() -{ - createBranch(false, &loops.top().continue_target); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-continue"); -} - -void Builder::createLoopExit() -{ - createBranch(false, &loops.top().merge); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-break"); -} - -void Builder::closeLoop() -{ - loops.pop(); -} - -void Builder::clearAccessChain() -{ - accessChain.base = NoResult; - accessChain.indexChain.clear(); - accessChain.instr = NoResult; - accessChain.swizzle.clear(); - accessChain.component = NoResult; - accessChain.preSwizzleBaseType = NoType; - accessChain.isRValue = false; - accessChain.coherentFlags.clear(); - accessChain.alignment = 0; -} - -// Comments in header -void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, - AccessChain::CoherentFlags coherentFlags, unsigned int alignment) -{ - accessChain.coherentFlags |= coherentFlags; - accessChain.alignment |= alignment; - - // swizzles can be stacked in GLSL, but simplified to a single - // one here; the base type doesn't change - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - - // if needed, propagate the swizzle for the current access chain - if (accessChain.swizzle.size() > 0) { - std::vector oldSwizzle = accessChain.swizzle; - accessChain.swizzle.resize(0); - for (unsigned int i = 0; i < swizzle.size(); ++i) { - assert(swizzle[i] < oldSwizzle.size()); - accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]); - } - } else - accessChain.swizzle = swizzle; - - // determine if we need to track this swizzle anymore - simplifyAccessChainSwizzle(); -} - -// Comments in header -void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - - // If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores. - if (accessChain.swizzle.size() > 0 && - getNumTypeComponents(getResultingAccessChainType()) != accessChain.swizzle.size() && - accessChain.component == NoResult) { - for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { - accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i])); - accessChain.instr = NoResult; - - Id base = collapseAccessChain(); - addDecoration(base, nonUniform); - - accessChain.indexChain.pop_back(); - accessChain.instr = NoResult; - - // dynamic component should be gone - assert(accessChain.component == NoResult); - - Id source = createCompositeExtract(rvalue, getContainedTypeId(getTypeId(rvalue)), i); - - // take LSB of alignment - alignment = alignment & ~(alignment & (alignment-1)); - if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - createStore(source, base, memoryAccess, scope, alignment); - } - } - else { - Id base = collapseAccessChain(); - addDecoration(base, nonUniform); - - Id source = rvalue; - - // dynamic component should be gone - assert(accessChain.component == NoResult); - - // If swizzle still exists, it may be out-of-order, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. - if (accessChain.swizzle.size() > 0) { - Id tempBaseId = createLoad(base, spv::NoPrecision); - source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); - } - - // take LSB of alignment - alignment = alignment & ~(alignment & (alignment-1)); - if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - createStore(source, base, memoryAccess, scope, alignment); - } -} - -// Comments in header -Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform, - Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, - spv::Scope scope, unsigned int alignment) -{ - Id id; - - if (accessChain.isRValue) { - // transfer access chain, but try to stay in registers - transferAccessChainSwizzle(false); - if (accessChain.indexChain.size() > 0) { - Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType; - - // if all the accesses are constants, we can use OpCompositeExtract - std::vector indexes; - bool constant = true; - for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { - if (isConstantScalar(accessChain.indexChain[i])) - indexes.push_back(getConstantScalar(accessChain.indexChain[i])); - else { - constant = false; - break; - } - } - - if (constant) { - id = createCompositeExtract(accessChain.base, swizzleBase, indexes); - setPrecision(id, precision); - } else { - Id lValue = NoResult; - if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) { - // make a new function variable for this r-value, using an initializer, - // and mark it as NonWritable so that downstream it can be detected as a lookup - // table - lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), - "indexable", accessChain.base); - addDecoration(lValue, DecorationNonWritable); - } else { - lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), - "indexable"); - // store into it - createStore(accessChain.base, lValue); - } - // move base to the new variable - accessChain.base = lValue; - accessChain.isRValue = false; - - // load through the access chain - id = createLoad(collapseAccessChain(), precision); - } - } else - id = accessChain.base; // no precision, it was set when this was defined - } else { - transferAccessChainSwizzle(true); - - // take LSB of alignment - alignment = alignment & ~(alignment & (alignment-1)); - if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - // load through the access chain - id = collapseAccessChain(); - // Apply nonuniform both to the access chain and the loaded value. - // Buffer accesses need the access chain decorated, and this is where - // loaded image types get decorated. TODO: This should maybe move to - // createImageTextureFunctionCall. - addDecoration(id, l_nonUniform); - id = createLoad(id, precision, memoryAccess, scope, alignment); - addDecoration(id, r_nonUniform); - } - - // Done, unless there are swizzles to do - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return id; - - // Do remaining swizzling - - // Do the basic swizzle - if (accessChain.swizzle.size() > 0) { - Id swizzledType = getScalarTypeId(getTypeId(id)); - if (accessChain.swizzle.size() > 1) - swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size()); - id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle); - } - - // Do the dynamic component - if (accessChain.component != NoResult) - id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision); - - addDecoration(id, r_nonUniform); - return id; -} - -Id Builder::accessChainGetLValue() -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - Id lvalue = collapseAccessChain(); - - // If swizzle exists, it is out-of-order or not full, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. This does not - // go with getting a direct l-value pointer. - assert(accessChain.swizzle.size() == 0); - assert(accessChain.component == NoResult); - - return lvalue; -} - -// comment in header -Id Builder::accessChainGetInferredType() -{ - // anything to operate on? - if (accessChain.base == NoResult) - return NoType; - Id type = getTypeId(accessChain.base); - - // do initial dereference - if (! accessChain.isRValue) - type = getContainedTypeId(type); - - // dereference each index - for (auto it = accessChain.indexChain.cbegin(); it != accessChain.indexChain.cend(); ++it) { - if (isStructType(type)) - type = getContainedTypeId(type, getConstantScalar(*it)); - else - type = getContainedTypeId(type); - } - - // dereference swizzle - if (accessChain.swizzle.size() == 1) - type = getContainedTypeId(type); - else if (accessChain.swizzle.size() > 1) - type = makeVectorType(getContainedTypeId(type), (int)accessChain.swizzle.size()); - - // dereference component selection - if (accessChain.component) - type = getContainedTypeId(type); - - return type; -} - -void Builder::dump(std::vector& out) const -{ - // Header, before first instructions: - out.push_back(MagicNumber); - out.push_back(spvVersion); - out.push_back(builderNumber); - out.push_back(uniqueId + 1); - out.push_back(0); - - // Capabilities - for (auto it = capabilities.cbegin(); it != capabilities.cend(); ++it) { - Instruction capInst(0, 0, OpCapability); - capInst.addImmediateOperand(*it); - capInst.dump(out); - } - - for (auto it = extensions.cbegin(); it != extensions.cend(); ++it) { - Instruction extInst(0, 0, OpExtension); - extInst.addStringOperand(it->c_str()); - extInst.dump(out); - } - - dumpInstructions(out, imports); - Instruction memInst(0, 0, OpMemoryModel); - memInst.addImmediateOperand(addressModel); - memInst.addImmediateOperand(memoryModel); - memInst.dump(out); - - // Instructions saved up while building: - dumpInstructions(out, entryPoints); - dumpInstructions(out, executionModes); - - // Debug instructions - dumpInstructions(out, strings); - dumpSourceInstructions(out); - for (int e = 0; e < (int)sourceExtensions.size(); ++e) { - Instruction sourceExtInst(0, 0, OpSourceExtension); - sourceExtInst.addStringOperand(sourceExtensions[e]); - sourceExtInst.dump(out); - } - dumpInstructions(out, names); - dumpModuleProcesses(out); - - // Annotation instructions - dumpInstructions(out, decorations); - - dumpInstructions(out, constantsTypesGlobals); - dumpInstructions(out, externals); - - // The functions - module.dump(out); -} - -// -// Protected methods. -// - -// Turn the described access chain in 'accessChain' into an instruction(s) -// computing its address. This *cannot* include complex swizzles, which must -// be handled after this is called. -// -// Can generate code. -Id Builder::collapseAccessChain() -{ - assert(accessChain.isRValue == false); - - // did we already emit an access chain for this? - if (accessChain.instr != NoResult) - return accessChain.instr; - - // If we have a dynamic component, we can still transfer - // that into a final operand to the access chain. We need to remap the - // dynamic component through the swizzle to get a new dynamic component to - // update. - // - // This was not done in transferAccessChainSwizzle() because it might - // generate code. - remapDynamicSwizzle(); - if (accessChain.component != NoResult) { - // transfer the dynamic component to the access chain - accessChain.indexChain.push_back(accessChain.component); - accessChain.component = NoResult; - } - - // note that non-trivial swizzling is left pending - - // do we have an access chain? - if (accessChain.indexChain.size() == 0) - return accessChain.base; - - // emit the access chain - StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base)); - accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain); - - return accessChain.instr; -} - -// For a dynamic component selection of a swizzle. -// -// Turn the swizzle and dynamic component into just a dynamic component. -// -// Generates code. -void Builder::remapDynamicSwizzle() -{ - // do we have a swizzle to remap a dynamic component through? - if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) { - // build a vector of the swizzle for the component to map into - std::vector components; - for (int c = 0; c < (int)accessChain.swizzle.size(); ++c) - components.push_back(makeUintConstant(accessChain.swizzle[c])); - Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size()); - Id map = makeCompositeConstant(mapType, components); - - // use it - accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component); - accessChain.swizzle.clear(); - } -} - -// clear out swizzle if it is redundant, that is reselecting the same components -// that would be present without the swizzle. -void Builder::simplifyAccessChainSwizzle() -{ - // If the swizzle has fewer components than the vector, it is subsetting, and must stay - // to preserve that fact. - if (getNumTypeComponents(accessChain.preSwizzleBaseType) > accessChain.swizzle.size()) - return; - - // if components are out of order, it is a swizzle - for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { - if (i != accessChain.swizzle[i]) - return; - } - - // otherwise, there is no need to track this swizzle - accessChain.swizzle.clear(); - if (accessChain.component == NoResult) - accessChain.preSwizzleBaseType = NoType; -} - -// To the extent any swizzling can become part of the chain -// of accesses instead of a post operation, make it so. -// If 'dynamic' is true, include transferring the dynamic component, -// otherwise, leave it pending. -// -// Does not generate code. just updates the access chain. -void Builder::transferAccessChainSwizzle(bool dynamic) -{ - // non existent? - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return; - - // too complex? - // (this requires either a swizzle, or generating code for a dynamic component) - if (accessChain.swizzle.size() > 1) - return; - - // single component, either in the swizzle and/or dynamic component - if (accessChain.swizzle.size() == 1) { - assert(accessChain.component == NoResult); - // handle static component selection - accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front())); - accessChain.swizzle.clear(); - accessChain.preSwizzleBaseType = NoType; - } else if (dynamic && accessChain.component != NoResult) { - assert(accessChain.swizzle.size() == 0); - // handle dynamic component - accessChain.indexChain.push_back(accessChain.component); - accessChain.preSwizzleBaseType = NoType; - accessChain.component = NoResult; - } -} - -// Utility method for creating a new block and setting the insert point to -// be in it. This is useful for flow-control operations that need a "dummy" -// block proceeding them (e.g. instructions after a discard, etc). -void Builder::createAndSetNoPredecessorBlock(const char* /*name*/) -{ - Block* block = new Block(getUniqueId(), buildPoint->getParent()); - block->setUnreachable(); - buildPoint->getParent().addBlock(block); - setBuildPoint(block); - - // if (name) - // addName(block->getId(), name); -} - -// Comments in header -void Builder::createBranch(bool implicit, Block* block) -{ - Instruction* branch = new Instruction(OpBranch); - branch->addIdOperand(block->getId()); - if (implicit) { - addInstructionNoDebugInfo(std::unique_ptr(branch)); - } - else { - addInstruction(std::unique_ptr(branch)); - } - block->addPredecessor(buildPoint); -} - -void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control) -{ - Instruction* merge = new Instruction(OpSelectionMerge); - merge->reserveOperands(2); - merge->addIdOperand(mergeBlock->getId()); - merge->addImmediateOperand(control); - addInstruction(std::unique_ptr(merge)); -} - -void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, - const std::vector& operands) -{ - Instruction* merge = new Instruction(OpLoopMerge); - merge->reserveOperands(operands.size() + 3); - merge->addIdOperand(mergeBlock->getId()); - merge->addIdOperand(continueBlock->getId()); - merge->addImmediateOperand(control); - for (int op = 0; op < (int)operands.size(); ++op) - merge->addImmediateOperand(operands[op]); - addInstruction(std::unique_ptr(merge)); -} - -void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock) -{ - Instruction* branch = new Instruction(OpBranchConditional); - branch->reserveOperands(3); - branch->addIdOperand(condition); - branch->addIdOperand(thenBlock->getId()); - branch->addIdOperand(elseBlock->getId()); - - // A conditional branch is always attached to a condition expression - addInstructionNoDebugInfo(std::unique_ptr(branch)); - - thenBlock->addPredecessor(buildPoint); - elseBlock->addPredecessor(buildPoint); -} - -// OpSource -// [OpSourceContinued] -// ... -void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& text, - std::vector& out) const -{ - const int maxWordCount = 0xFFFF; - const int opSourceWordCount = 4; - const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1; - - if (sourceLang != SourceLanguageUnknown) { - // OpSource Language Version File Source - Instruction sourceInst(NoResult, NoType, OpSource); - sourceInst.reserveOperands(3); - sourceInst.addImmediateOperand(sourceLang); - sourceInst.addImmediateOperand(sourceVersion); - // File operand - if (fileId != NoResult) { - sourceInst.addIdOperand(fileId); - // Source operand - if (text.size() > 0) { - int nextByte = 0; - std::string subString; - while ((int)text.size() - nextByte > 0) { - subString = text.substr(nextByte, nonNullBytesPerInstruction); - if (nextByte == 0) { - // OpSource - sourceInst.addStringOperand(subString.c_str()); - sourceInst.dump(out); - } else { - // OpSourcContinued - Instruction sourceContinuedInst(OpSourceContinued); - sourceContinuedInst.addStringOperand(subString.c_str()); - sourceContinuedInst.dump(out); - } - nextByte += nonNullBytesPerInstruction; - } - } else - sourceInst.dump(out); - } else - sourceInst.dump(out); - } -} - -// Dump an OpSource[Continued] sequence for the source and every include file -void Builder::dumpSourceInstructions(std::vector& out) const -{ - if (emitNonSemanticShaderDebugInfo) return; - dumpSourceInstructions(mainFileId, sourceText, out); - for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr) - dumpSourceInstructions(iItr->first, *iItr->second, out); -} - -template void Builder::dumpInstructions(std::vector& out, const Range& instructions) const -{ - for (const auto& inst : instructions) { - inst->dump(out); - } -} - -void Builder::dumpModuleProcesses(std::vector& out) const -{ - for (int i = 0; i < (int)moduleProcesses.size(); ++i) { - Instruction moduleProcessed(OpModuleProcessed); - moduleProcessed.addStringOperand(moduleProcesses[i]); - moduleProcessed.dump(out); - } -} - -bool Builder::DecorationInstructionLessThan::operator()(const std::unique_ptr& lhs, - const std::unique_ptr& rhs) const -{ - // Order by the id to which the decoration applies first. This is more intuitive. - assert(lhs->isIdOperand(0) && rhs->isIdOperand(0)); - if (lhs->getIdOperand(0) != rhs->getIdOperand(0)) { - return lhs->getIdOperand(0) < rhs->getIdOperand(0); - } - - if (lhs->getOpCode() != rhs->getOpCode()) - return lhs->getOpCode() < rhs->getOpCode(); - - // Now compare the operands. - int minSize = std::min(lhs->getNumOperands(), rhs->getNumOperands()); - for (int i = 1; i < minSize; ++i) { - if (lhs->isIdOperand(i) != rhs->isIdOperand(i)) { - return lhs->isIdOperand(i) < rhs->isIdOperand(i); - } - - if (lhs->isIdOperand(i)) { - if (lhs->getIdOperand(i) != rhs->getIdOperand(i)) { - return lhs->getIdOperand(i) < rhs->getIdOperand(i); - } - } else { - if (lhs->getImmediateOperand(i) != rhs->getImmediateOperand(i)) { - return lhs->getImmediateOperand(i) < rhs->getImmediateOperand(i); - } - } - } - - if (lhs->getNumOperands() != rhs->getNumOperands()) - return lhs->getNumOperands() < rhs->getNumOperands(); - - // In this case they are equal. - return false; -} -} // end spv namespace diff --git a/include/SPIRV/SpvBuilder.h b/include/SPIRV/SpvBuilder.h deleted file mode 100644 index 44377acb..00000000 --- a/include/SPIRV/SpvBuilder.h +++ /dev/null @@ -1,1016 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2020 Google, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// "Builder" is an interface to fully build SPIR-V IR. Allocate one of -// these to build (a thread safe) internal SPIR-V representation (IR), -// and then dump it as a binary stream according to the SPIR-V specification. -// -// A Builder has a 1:1 relationship with a SPIR-V module. -// - -#pragma once -#ifndef SpvBuilder_H -#define SpvBuilder_H - -#include "Logger.h" -#define SPV_ENABLE_UTILITY_CODE -#include "spirv.hpp" -#include "spvIR.h" -namespace spv { - #include "GLSL.ext.KHR.h" - #include "NonSemanticShaderDebugInfo100.h" -} - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace spv { - -typedef enum { - Spv_1_0 = (1 << 16), - Spv_1_1 = (1 << 16) | (1 << 8), - Spv_1_2 = (1 << 16) | (2 << 8), - Spv_1_3 = (1 << 16) | (3 << 8), - Spv_1_4 = (1 << 16) | (4 << 8), - Spv_1_5 = (1 << 16) | (5 << 8), -} SpvVersion; - -class Builder { -public: - Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); - virtual ~Builder(); - - static const int maxMatrixSize = 4; - - unsigned int getSpvVersion() const { return spvVersion; } - - void setSource(spv::SourceLanguage lang, int version) - { - sourceLang = lang; - sourceVersion = version; - } - spv::Id getStringId(const std::string& str) - { - auto sItr = stringIds.find(str); - if (sItr != stringIds.end()) - return sItr->second; - spv::Id strId = getUniqueId(); - Instruction* fileString = new Instruction(strId, NoType, OpString); - const char* file_c_str = str.c_str(); - fileString->addStringOperand(file_c_str); - strings.push_back(std::unique_ptr(fileString)); - module.mapInstruction(fileString); - stringIds[file_c_str] = strId; - return strId; - } - - spv::Id getMainFileId() const { return mainFileId; } - - // Initialize the main source file name - void setDebugMainSourceFile(const std::string& file) - { - if (trackDebugInfo) { - dirtyLineTracker = true; - mainFileId = getStringId(file); - currentFileId = mainFileId; - } - } - - // Set the debug source location tracker in the builder. - // The upcoming instructions in basic blocks will be associated to this location. - void setDebugSourceLocation(int line, const char* filename) - { - if (trackDebugInfo) { - dirtyLineTracker = true; - if (line != 0) { - // TODO: This is special handling of some AST nodes having (untracked) line 0. - // But they should have a valid line number. - currentLine = line; - if (filename) { - currentFileId = getStringId(filename); - } - } - } - } - - void setSourceText(const std::string& text) { sourceText = text; } - void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } - void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } - void setEmitSpirvDebugInfo() - { - trackDebugInfo = true; - emitSpirvDebugInfo = true; - } - void setEmitNonSemanticShaderDebugInfo(bool emitSourceText) - { - trackDebugInfo = true; - emitNonSemanticShaderDebugInfo = true; - importNonSemanticShaderDebugInfoInstructions(); - - if (emitSourceText) { - emitNonSemanticShaderDebugSource = emitSourceText; - } - } - void addExtension(const char* ext) { extensions.insert(ext); } - void removeExtension(const char* ext) - { - extensions.erase(ext); - } - void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) - { - if (getSpvVersion() < static_cast(incorporatedVersion)) - addExtension(ext); - } - void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) - { - removeExtension(baseExt); - addIncorporatedExtension(promoExt, incorporatedVersion); - } - void addInclude(const std::string& name, const std::string& text) - { - spv::Id incId = getStringId(name); - includeFiles[incId] = &text; - } - Id import(const char*); - void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) - { - addressModel = addr; - memoryModel = mem; - } - - void addCapability(spv::Capability cap) { capabilities.insert(cap); } - - // To get a new for anything needing a new one. - Id getUniqueId() { return ++uniqueId; } - - // To get a set of new s, e.g., for a set of function parameters - Id getUniqueIds(int numIds) - { - Id id = uniqueId + 1; - uniqueId += numIds; - return id; - } - - // For creating new types (will return old type if the requested one was already made). - Id makeVoidType(); - Id makeBoolType(); - Id makePointer(StorageClass, Id pointee); - Id makeForwardPointer(StorageClass); - Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); - Id makeIntegerType(int width, bool hasSign); // generic - Id makeIntType(int width) { return makeIntegerType(width, true); } - Id makeUintType(int width) { return makeIntegerType(width, false); } - Id makeFloatType(int width); - Id makeStructType(const std::vector& members, const char* name, bool const compilerGenerated = true); - Id makeStructResultType(Id type0, Id type1); - Id makeVectorType(Id component, int size); - Id makeMatrixType(Id component, int cols, int rows); - Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration - Id makeRuntimeArray(Id element); - Id makeFunctionType(Id returnType, const std::vector& paramTypes); - Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); - Id makeSamplerType(); - Id makeSampledImageType(Id imageType); - Id makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id cols, Id use); - Id makeCooperativeMatrixTypeNV(Id component, Id scope, Id rows, Id cols); - Id makeCooperativeMatrixTypeWithSameShape(Id component, Id otherType); - Id makeGenericType(spv::Op opcode, std::vector& operands); - - // SPIR-V NonSemantic Shader DebugInfo Instructions - struct DebugTypeLoc { - std::string name {}; - int line {0}; - int column {0}; - }; - std::unordered_map debugTypeLocs; - Id makeDebugInfoNone(); - Id makeBoolDebugType(int const size); - Id makeIntegerDebugType(int const width, bool const hasSign); - Id makeFloatDebugType(int const width); - Id makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType); - Id makeArrayDebugType(Id const baseType, Id const componentCount); - Id makeVectorDebugType(Id const baseType, int const componentCount); - Id makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor = true); - Id makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc); - Id makeCompositeDebugType(std::vector const& memberTypes, char const*const name, - NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType = false); - Id makePointerDebugType(StorageClass storageClass, Id const baseType); - Id makeForwardPointerDebugType(StorageClass storageClass); - Id makeDebugSource(const Id fileName); - Id makeDebugCompilationUnit(); - Id createDebugGlobalVariable(Id const type, char const*const name, Id const variable); - Id createDebugLocalVariable(Id type, char const*const name, size_t const argNumber = 0); - Id makeDebugExpression(); - Id makeDebugDeclare(Id const debugLocalVariable, Id const pointer); - Id makeDebugValue(Id const debugLocalVariable, Id const value); - Id makeDebugFunctionType(Id returnType, const std::vector& paramTypes); - Id makeDebugFunction(Function* function, Id nameId, Id funcTypeId); - Id makeDebugLexicalBlock(uint32_t line, uint32_t column); - std::string unmangleFunctionName(std::string const& name) const; - - // Initialize non-semantic debug information for a function, including those of: - // - The function definition - // - The function parameters - void setupFunctionDebugInfo(Function* function, const char* name, const std::vector& paramTypes, - const std::vector& paramNames); - - // accelerationStructureNV type - Id makeAccelerationStructureType(); - // rayQueryEXT type - Id makeRayQueryType(); - // hitObjectNV type - Id makeHitObjectNVType(); - - // For querying about types. - Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } - Id getDerefTypeId(Id resultId) const; - Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } - Op getTypeClass(Id typeId) const { return getOpCode(typeId); } - Op getMostBasicTypeClass(Id typeId) const; - unsigned int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } - unsigned int getNumTypeConstituents(Id typeId) const; - unsigned int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } - Id getScalarTypeId(Id typeId) const; - Id getContainedTypeId(Id typeId) const; - Id getContainedTypeId(Id typeId, int) const; - StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } - ImageFormat getImageTypeFormat(Id typeId) const - { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } - Id getResultingAccessChainType() const; - Id getIdOperand(Id resultId, int idx) { return module.getInstruction(resultId)->getIdOperand(idx); } - - bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } - bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } - bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } - bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } - bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } - bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } - bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } - bool isTensorView(Id resultId)const { return isTensorViewType(getTypeId(resultId)); } - - bool isBoolType(Id typeId) - { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } - bool isIntType(Id typeId) const - { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } - bool isUintType(Id typeId) const - { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } - bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } - bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } - bool isScalarType(Id typeId) const - { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || - getTypeClass(typeId) == OpTypeBool; } - bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } - bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } - bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } - bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } - bool isCooperativeMatrixType(Id typeId)const - { - return getTypeClass(typeId) == OpTypeCooperativeMatrixKHR || getTypeClass(typeId) == OpTypeCooperativeMatrixNV; - } - bool isTensorViewType(Id typeId) const { return getTypeClass(typeId) == OpTypeTensorViewNV; } - bool isAggregateType(Id typeId) const - { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } - bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } - bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } - bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } - bool containsType(Id typeId, Op typeOp, unsigned int width) const; - bool containsPhysicalStorageBufferOrArray(Id typeId) const; - - bool isConstantOpCode(Op opcode) const; - bool isSpecConstantOpCode(Op opcode) const; - bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } - bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } - bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } - unsigned int getConstantScalar(Id resultId) const - { return module.getInstruction(resultId)->getImmediateOperand(0); } - StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } - - bool isVariableOpCode(Op opcode) const { return opcode == OpVariable; } - bool isVariable(Id resultId) const { return isVariableOpCode(getOpCode(resultId)); } - bool isGlobalStorage(Id resultId) const { return getStorageClass(resultId) != StorageClassFunction; } - bool isGlobalVariable(Id resultId) const { return isVariable(resultId) && isGlobalStorage(resultId); } - // See if a resultId is valid for use as an initializer. - bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); } - - int getScalarTypeWidth(Id typeId) const - { - Id scalarTypeId = getScalarTypeId(typeId); - assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); - return module.getInstruction(scalarTypeId)->getImmediateOperand(0); - } - - unsigned int getTypeNumColumns(Id typeId) const - { - assert(isMatrixType(typeId)); - return getNumTypeConstituents(typeId); - } - unsigned int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } - unsigned int getTypeNumRows(Id typeId) const - { - assert(isMatrixType(typeId)); - return getNumTypeComponents(getContainedTypeId(typeId)); - } - unsigned int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } - - Dim getTypeDimensionality(Id typeId) const - { - assert(isImageType(typeId)); - return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); - } - Id getImageType(Id resultId) const - { - Id typeId = getTypeId(resultId); - assert(isImageType(typeId) || isSampledImageType(typeId)); - return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; - } - bool isArrayedImageType(Id typeId) const - { - assert(isImageType(typeId)); - return module.getInstruction(typeId)->getImmediateOperand(3) != 0; - } - - // For making new constants (will return old constant if the requested one was already made). - Id makeNullConstant(Id typeId); - Id makeBoolConstant(bool b, bool specConstant = false); - Id makeIntConstant(Id typeId, unsigned value, bool specConstant); - Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); - Id makeInt8Constant(int i, bool specConstant = false) - { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } - Id makeUint8Constant(unsigned u, bool specConstant = false) - { return makeIntConstant(makeUintType(8), u, specConstant); } - Id makeInt16Constant(int i, bool specConstant = false) - { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } - Id makeUint16Constant(unsigned u, bool specConstant = false) - { return makeIntConstant(makeUintType(16), u, specConstant); } - Id makeIntConstant(int i, bool specConstant = false) - { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } - Id makeUintConstant(unsigned u, bool specConstant = false) - { return makeIntConstant(makeUintType(32), u, specConstant); } - Id makeInt64Constant(long long i, bool specConstant = false) - { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } - Id makeUint64Constant(unsigned long long u, bool specConstant = false) - { return makeInt64Constant(makeUintType(64), u, specConstant); } - Id makeFloatConstant(float f, bool specConstant = false); - Id makeDoubleConstant(double d, bool specConstant = false); - Id makeFloat16Constant(float f16, bool specConstant = false); - Id makeFpConstant(Id type, double d, bool specConstant = false); - - Id importNonSemanticShaderDebugInfoInstructions(); - - // Turn the array of constants into a proper spv constant of the requested type. - Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); - - // Methods for adding information outside the CFG. - Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); - void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); - void addExecutionMode(Function*, ExecutionMode mode, const std::vector& literals); - void addExecutionModeId(Function*, ExecutionMode mode, const std::vector& operandIds); - void addName(Id, const char* name); - void addMemberName(Id, int member, const char* name); - void addDecoration(Id, Decoration, int num = -1); - void addDecoration(Id, Decoration, const char*); - void addDecoration(Id, Decoration, const std::vector& literals); - void addDecoration(Id, Decoration, const std::vector& strings); - void addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType); - void addDecorationId(Id id, Decoration, Id idDecoration); - void addDecorationId(Id id, Decoration, const std::vector& operandIds); - void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); - void addMemberDecoration(Id, unsigned int member, Decoration, const char*); - void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector& literals); - void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector& strings); - - // At the end of what block do the next create*() instructions go? - // Also reset current last DebugScope and current source line to unknown - void setBuildPoint(Block* bp) { - buildPoint = bp; - dirtyLineTracker = true; - dirtyScopeTracker = true; - } - Block* getBuildPoint() const { return buildPoint; } - - // Append an instruction to the end of the current build point. - // Optionally, additional debug info instructions may also be prepended. - void addInstruction(std::unique_ptr inst); - - // Append an instruction to the end of the current build point without prepending any debug instructions. - // This is useful for insertion of some debug info instructions themselves or some control flow instructions - // that are attached to its predecessor instruction. - void addInstructionNoDebugInfo(std::unique_ptr inst); - - // Make the entry-point function. The returned pointer is only valid - // for the lifetime of this builder. - Function* makeEntryPoint(const char*); - - // Make a shader-style function, and create its entry block if entry is non-zero. - // Return the function, pass back the entry. - // The returned pointer is only valid for the lifetime of this builder. - Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, - const std::vector& paramTypes, - const std::vector>& precisions, Block** entry = nullptr); - - // Create a return. An 'implicit' return is one not appearing in the source - // code. In the case of an implicit return, no post-return block is inserted. - void makeReturn(bool implicit, Id retVal = 0); - - // Initialize state and generate instructions for new lexical scope - void enterLexicalBlock(uint32_t line, uint32_t column); - - // Set state and generate instructions to exit current lexical scope - void leaveLexicalBlock(); - - // Prepare builder for generation of instructions for a function. - void enterFunction(Function const* function); - - // Generate all the code needed to finish up a function. - void leaveFunction(); - - // Create block terminator instruction for certain statements like - // discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT - void makeStatementTerminator(spv::Op opcode, const char *name); - - // Create block terminator instruction for statements that have input operands - // such as OpEmitMeshTasksEXT - void makeStatementTerminator(spv::Op opcode, const std::vector& operands, const char* name); - - // Create a global or function local or IO variable. - Id createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name = nullptr, - Id initializer = NoResult, bool const compilerGenerated = true); - - // Create an intermediate with an undefined value. - Id createUndefined(Id type); - - // Store into an Id and return the l-value - void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, - spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); - - // Load from an Id and return it - Id createLoad(Id lValue, spv::Decoration precision, - spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, - spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); - - // Create an OpAccessChain instruction - Id createAccessChain(StorageClass, Id base, const std::vector& offsets); - - // Create an OpArrayLength instruction - Id createArrayLength(Id base, unsigned int member); - - // Create an OpCooperativeMatrixLengthKHR instruction - Id createCooperativeMatrixLengthKHR(Id type); - // Create an OpCooperativeMatrixLengthNV instruction - Id createCooperativeMatrixLengthNV(Id type); - - // Create an OpCompositeExtract instruction - Id createCompositeExtract(Id composite, Id typeId, unsigned index); - Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); - Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); - Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); - - Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); - Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); - - void createNoResultOp(Op); - void createNoResultOp(Op, Id operand); - void createNoResultOp(Op, const std::vector& operands); - void createNoResultOp(Op, const std::vector& operands); - void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); - void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); - Id createUnaryOp(Op, Id typeId, Id operand); - Id createBinOp(Op, Id typeId, Id operand1, Id operand2); - Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); - Id createOp(Op, Id typeId, const std::vector& operands); - Id createOp(Op, Id typeId, const std::vector& operands); - Id createFunctionCall(spv::Function*, const std::vector&); - Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); - - // Take an rvalue (source) and a set of channels to extract from it to - // make a new rvalue, which is returned. - Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); - - // Take a copy of an lvalue (target) and a source of components, and set the - // source components into the lvalue where the 'channels' say to put them. - // An updated version of the target is returned. - // (No true lvalue or stores are used.) - Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); - - // If both the id and precision are valid, the id - // gets tagged with the requested precision. - // The passed in id is always the returned id, to simplify use patterns. - Id setPrecision(Id id, Decoration precision) - { - if (precision != NoPrecision && id != NoResult) - addDecoration(id, precision); - - return id; - } - - // Can smear a scalar to a vector for the following forms: - // - promoteScalar(scalar, vector) // smear scalar to width of vector - // - promoteScalar(vector, scalar) // smear scalar to width of vector - // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to - // - promoteScalar(scalar, scalar) // do nothing - // Other forms are not allowed. - // - // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. - // The type of the created vector is a vector of components of the same type as the scalar. - // - // Note: One of the arguments will change, with the result coming back that way rather than - // through the return value. - void promoteScalar(Decoration precision, Id& left, Id& right); - - // Make a value by smearing the scalar to fill the type. - // vectorType should be the correct type for making a vector of scalarVal. - // (No conversions are done.) - Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); - - // Create a call to a built-in function. - Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); - - // List of parameters used to create a texture operation - struct TextureParameters { - Id sampler; - Id coords; - Id bias; - Id lod; - Id Dref; - Id offset; - Id offsets; - Id gradX; - Id gradY; - Id sample; - Id component; - Id texelOut; - Id lodClamp; - Id granularity; - Id coarse; - bool nonprivate; - bool volatil; - }; - - // Select the correct texture operation based on all inputs, and emit the correct instruction - Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, - bool noImplicit, const TextureParameters&, ImageOperandsMask); - - // Emit the OpTextureQuery* instruction that was passed in. - // Figure out the right return value and type, and return it. - Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); - - Id createSamplePositionCall(Decoration precision, Id, Id); - - Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); - Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); - - // Reduction comparison for composites: For equal and not-equal resulting in a scalar. - Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); - - // OpCompositeConstruct - Id createCompositeConstruct(Id typeId, const std::vector& constituents); - - // vector or scalar constructor - Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); - - // matrix constructor - Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); - - // coopmat conversion - Id createCooperativeMatrixConversion(Id typeId, Id source); - Id createCooperativeMatrixReduce(Op opcode, Id typeId, Id source, unsigned int mask, Id func); - Id createCooperativeMatrixPerElementOp(Id typeId, const std::vector& operands); - - // Helper to use for building nested control flow with if-then-else. - class If { - public: - If(Id condition, unsigned int ctrl, Builder& builder); - ~If() {} - - void makeBeginElse(); - void makeEndIf(); - - private: - If(const If&); - If& operator=(If&); - - Builder& builder; - Id condition; - unsigned int control; - Function* function; - Block* headerBlock; - Block* thenBlock; - Block* elseBlock; - Block* mergeBlock; - }; - - // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing - // any case/default labels, all separated by one or more case/default labels. Each possible - // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this - // number space. How to compute the value is given by 'condition', as in switch(condition). - // - // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. - // - // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). - // - // Returns the right set of basic blocks to start each code segment with, so that the caller's - // recursion stack can hold the memory for it. - // - void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); - - // Add a branch to the innermost switch's merge block. - void addSwitchBreak(bool implicit); - - // Move to the next code segment, passing in the return argument in makeSwitch() - void nextSwitchSegment(std::vector& segmentBB, int segment); - - // Finish off the innermost switch. - void endSwitch(std::vector& segmentBB); - - struct LoopBlocks { - LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : - head(head), body(body), merge(merge), continue_target(continue_target) { } - Block &head, &body, &merge, &continue_target; - private: - LoopBlocks(); - LoopBlocks& operator=(const LoopBlocks&) = delete; - }; - - // Start a new loop and prepare the builder to generate code for it. Until - // closeLoop() is called for this loop, createLoopContinue() and - // createLoopExit() will target its corresponding blocks. - LoopBlocks& makeNewLoop(); - - // Create a new block in the function containing the build point. Memory is - // owned by the function object. - Block& makeNewBlock(); - - // Add a branch to the continue_target of the current (innermost) loop. - void createLoopContinue(); - - // Add an exit (e.g. "break") from the innermost loop that we're currently - // in. - void createLoopExit(); - - // Close the innermost loop that you're in - void closeLoop(); - - // - // Access chain design for an R-Value vs. L-Value: - // - // There is a single access chain the builder is building at - // any particular time. Such a chain can be used to either to a load or - // a store, when desired. - // - // Expressions can be r-values, l-values, or both, or only r-values: - // a[b.c].d = .... // l-value - // ... = a[b.c].d; // r-value, that also looks like an l-value - // ++a[b.c].d; // r-value and l-value - // (x + y)[2]; // r-value only, can't possibly be l-value - // - // Computing an r-value means generating code. Hence, - // r-values should only be computed when they are needed, not speculatively. - // - // Computing an l-value means saving away information for later use in the compiler, - // no code is generated until the l-value is later dereferenced. It is okay - // to speculatively generate an l-value, just not okay to speculatively dereference it. - // - // The base of the access chain (the left-most variable or expression - // from which everything is based) can be set either as an l-value - // or as an r-value. Most efficient would be to set an l-value if one - // is available. If an expression was evaluated, the resulting r-value - // can be set as the chain base. - // - // The users of this single access chain can save and restore if they - // want to nest or manage multiple chains. - // - - struct AccessChain { - Id base; // for l-values, pointer to the base object, for r-values, the base object - std::vector indexChain; - Id instr; // cache the instruction that generates this access chain - std::vector swizzle; // each std::vector element selects the next GLSL component number - Id component; // a dynamic component index, can coexist with a swizzle, - // done after the swizzle, NoResult if not present - Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; - // NoType unless a swizzle or component is present - bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value - unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. - // Only tracks base and (optional) component selection alignment. - - // Accumulate whether anything in the chain of structures has coherent decorations. - struct CoherentFlags { - CoherentFlags() { clear(); } - bool isVolatile() const { return volatil; } - bool isNonUniform() const { return nonUniform; } - bool anyCoherent() const { - return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || - subgroupcoherent || shadercallcoherent; - } - - unsigned coherent : 1; - unsigned devicecoherent : 1; - unsigned queuefamilycoherent : 1; - unsigned workgroupcoherent : 1; - unsigned subgroupcoherent : 1; - unsigned shadercallcoherent : 1; - unsigned nonprivate : 1; - unsigned volatil : 1; - unsigned isImage : 1; - unsigned nonUniform : 1; - - void clear() { - coherent = 0; - devicecoherent = 0; - queuefamilycoherent = 0; - workgroupcoherent = 0; - subgroupcoherent = 0; - shadercallcoherent = 0; - nonprivate = 0; - volatil = 0; - isImage = 0; - nonUniform = 0; - } - - CoherentFlags operator |=(const CoherentFlags &other) { - coherent |= other.coherent; - devicecoherent |= other.devicecoherent; - queuefamilycoherent |= other.queuefamilycoherent; - workgroupcoherent |= other.workgroupcoherent; - subgroupcoherent |= other.subgroupcoherent; - shadercallcoherent |= other.shadercallcoherent; - nonprivate |= other.nonprivate; - volatil |= other.volatil; - isImage |= other.isImage; - nonUniform |= other.nonUniform; - return *this; - } - }; - CoherentFlags coherentFlags; - }; - - // - // the SPIR-V builder maintains a single active chain that - // the following methods operate on - // - - // for external save and restore - AccessChain getAccessChain() { return accessChain; } - void setAccessChain(AccessChain newChain) { accessChain = newChain; } - - // clear accessChain - void clearAccessChain(); - - // set new base as an l-value base - void setAccessChainLValue(Id lValue) - { - assert(isPointer(lValue)); - accessChain.base = lValue; - } - - // set new base value as an r-value - void setAccessChainRValue(Id rValue) - { - accessChain.isRValue = true; - accessChain.base = rValue; - } - - // push offset onto the end of the chain - void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) - { - accessChain.indexChain.push_back(offset); - accessChain.coherentFlags |= coherentFlags; - accessChain.alignment |= alignment; - } - - // push new swizzle onto the end of any existing swizzle, merging into a single swizzle - void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, - AccessChain::CoherentFlags coherentFlags, unsigned int alignment); - - // push a dynamic component selection onto the access chain, only applicable with a - // non-trivial swizzle or no swizzle - void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, - unsigned int alignment) - { - if (accessChain.swizzle.size() != 1) { - accessChain.component = component; - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - } - accessChain.coherentFlags |= coherentFlags; - accessChain.alignment |= alignment; - } - - // use accessChain and swizzle to store value - void accessChainStore(Id rvalue, Decoration nonUniform, - spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, - spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); - - // use accessChain and swizzle to load an r-value - Id accessChainLoad(Decoration precision, Decoration l_nonUniform, Decoration r_nonUniform, Id ResultType, - spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, - unsigned int alignment = 0); - - // Return whether or not the access chain can be represented in SPIR-V - // as an l-value. - // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. - bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } - - // get the direct pointer for an l-value - Id accessChainGetLValue(); - - // Get the inferred SPIR-V type of the result of the current access chain, - // based on the type of the base and the chain of dereferences. - Id accessChainGetInferredType(); - - // Add capabilities, extensions, remove unneeded decorations, etc., - // based on the resulting SPIR-V. - void postProcess(bool compileOnly); - - // Prune unreachable blocks in the CFG and remove unneeded decorations. - void postProcessCFG(); - - // Add capabilities, extensions based on instructions in the module. - void postProcessFeatures(); - // Hook to visit each instruction in a block in a function - void postProcess(Instruction&); - // Hook to visit each non-32-bit sized float/int operation in a block. - void postProcessType(const Instruction&, spv::Id typeId); - // move OpSampledImage instructions to be next to their users. - void postProcessSamplers(); - - void dump(std::vector&) const; - - // Add a branch to the target block. - // If set implicit, the branch instruction shouldn't have debug source location. - void createBranch(bool implicit, Block* block); - void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); - void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, - const std::vector& operands); - - // Sets to generate opcode for specialization constants. - void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } - // Sets to generate opcode for non-specialization constants (normal mode). - void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } - // Check if the builder is generating code for spec constants. - bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } - - void setUseReplicatedComposites(bool use) { useReplicatedComposites = use; } - - protected: - Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); - Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); - Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); - Id findStructConstant(Id typeId, const std::vector& comps); - Id collapseAccessChain(); - void remapDynamicSwizzle(); - void transferAccessChainSwizzle(bool dynamic); - void simplifyAccessChainSwizzle(); - void createAndSetNoPredecessorBlock(const char*); - void createSelectionMerge(Block* mergeBlock, unsigned int control); - void dumpSourceInstructions(std::vector&) const; - void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; - template void dumpInstructions(std::vector& out, const Range& instructions) const; - void dumpModuleProcesses(std::vector&) const; - spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) - const; - struct DecorationInstructionLessThan { - bool operator()(const std::unique_ptr& lhs, const std::unique_ptr& rhs) const; - }; - - unsigned int spvVersion; // the version of SPIR-V to emit in the header - SourceLanguage sourceLang; - int sourceVersion; - spv::Id nonSemanticShaderCompilationUnitId {0}; - spv::Id nonSemanticShaderDebugInfo {0}; - spv::Id debugInfoNone {0}; - spv::Id debugExpression {0}; // Debug expression with zero operations. - std::string sourceText; - - // True if an new OpLine/OpDebugLine may need to be inserted. Either: - // 1. The current debug location changed - // 2. The current build point changed - bool dirtyLineTracker; - int currentLine = 0; - // OpString id of the current file name. Always 0 if debug info is off. - spv::Id currentFileId = 0; - // OpString id of the main file name. Always 0 if debug info is off. - spv::Id mainFileId = 0; - - // True if an new OpDebugScope may need to be inserted. Either: - // 1. A new lexical block is pushed - // 2. The current build point changed - bool dirtyScopeTracker; - std::stack currentDebugScopeId; - - // This flag toggles tracking of debug info while building the SPIR-V. - bool trackDebugInfo = false; - // This flag toggles emission of SPIR-V debug instructions, like OpLine and OpSource. - bool emitSpirvDebugInfo = false; - // This flag toggles emission of Non-Semantic Debug extension debug instructions. - bool emitNonSemanticShaderDebugInfo = false; - bool restoreNonSemanticShaderDebugInfo = false; - bool emitNonSemanticShaderDebugSource = false; - - std::set extensions; - std::vector sourceExtensions; - std::vector moduleProcesses; - AddressingModel addressModel; - MemoryModel memoryModel; - std::set capabilities; - int builderNumber; - Module module; - Block* buildPoint; - Id uniqueId; - Function* entryPointFunction; - bool generatingOpCodeForSpecConst; - bool useReplicatedComposites { false }; - AccessChain accessChain; - - // special blocks of instructions for output - std::vector > strings; - std::vector > imports; - std::vector > entryPoints; - std::vector > executionModes; - std::vector > names; - std::set, DecorationInstructionLessThan> decorations; - std::vector > constantsTypesGlobals; - std::vector > externals; - std::vector > functions; - - // not output, internally used for quick & dirty canonical (unique) creation - - // map type opcodes to constant inst. - std::unordered_map> groupedConstants; - // map struct-id to constant instructions - std::unordered_map> groupedStructConstants; - // map type opcodes to type instructions - std::unordered_map> groupedTypes; - // map type opcodes to debug type instructions - std::unordered_map> groupedDebugTypes; - // list of OpConstantNull instructions - std::vector nullConstants; - - // stack of switches - std::stack switchMerges; - - // Our loop stack. - std::stack loops; - - // map from strings to their string ids - std::unordered_map stringIds; - - // map from include file name ids to their contents - std::map includeFiles; - - // map from core id to debug id - std::map debugId; - - // map from file name string id to DebugSource id - std::unordered_map debugSourceId; - - // The stream for outputting warnings and errors. - SpvBuildLogger* logger; -}; // end Builder class - -} // end spv namespace - -#endif // SpvBuilder_H diff --git a/include/SPIRV/SpvPostProcess.cpp b/include/SPIRV/SpvPostProcess.cpp deleted file mode 100644 index 4cd01102..00000000 --- a/include/SPIRV/SpvPostProcess.cpp +++ /dev/null @@ -1,551 +0,0 @@ -// -// Copyright (C) 2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Post-processing for SPIR-V IR, in internal form, not standard binary form. -// - -#include -#include - -#include -#include -#include - -#include "SpvBuilder.h" -#include "spirv.hpp" - -namespace spv { - #include "GLSL.std.450.h" - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "GLSL.ext.QCOM.h" -} - -namespace spv { - -// Hook to visit each operand type and result type of an instruction. -// Will be called multiple times for one instruction, once for each typed -// operand and the result. -void Builder::postProcessType(const Instruction& inst, Id typeId) -{ - // Characterize the type being questioned - Id basicTypeOp = getMostBasicTypeClass(typeId); - int width = 0; - if (basicTypeOp == OpTypeFloat || basicTypeOp == OpTypeInt) - width = getScalarTypeWidth(typeId); - - // Do opcode-specific checks - switch (inst.getOpCode()) { - case OpLoad: - case OpStore: - if (basicTypeOp == OpTypeStruct) { - if (containsType(typeId, OpTypeInt, 8)) - addCapability(CapabilityInt8); - if (containsType(typeId, OpTypeInt, 16)) - addCapability(CapabilityInt16); - if (containsType(typeId, OpTypeFloat, 16)) - addCapability(CapabilityFloat16); - } else { - StorageClass storageClass = getStorageClass(inst.getIdOperand(0)); - if (width == 8) { - switch (storageClass) { - case StorageClassPhysicalStorageBufferEXT: - case StorageClassUniform: - case StorageClassStorageBuffer: - case StorageClassPushConstant: - break; - default: - addCapability(CapabilityInt8); - break; - } - } else if (width == 16) { - switch (storageClass) { - case StorageClassPhysicalStorageBufferEXT: - case StorageClassUniform: - case StorageClassStorageBuffer: - case StorageClassPushConstant: - case StorageClassInput: - case StorageClassOutput: - break; - default: - if (basicTypeOp == OpTypeInt) - addCapability(CapabilityInt16); - if (basicTypeOp == OpTypeFloat) - addCapability(CapabilityFloat16); - break; - } - } - } - break; - case OpCopyObject: - break; - case OpFConvert: - case OpSConvert: - case OpUConvert: - // Look for any 8/16-bit storage capabilities. If there are none, assume that - // the convert instruction requires the Float16/Int8/16 capability. - if (containsType(typeId, OpTypeFloat, 16) || containsType(typeId, OpTypeInt, 16)) { - bool foundStorage = false; - for (auto it = capabilities.begin(); it != capabilities.end(); ++it) { - spv::Capability cap = *it; - if (cap == spv::CapabilityStorageInputOutput16 || - cap == spv::CapabilityStoragePushConstant16 || - cap == spv::CapabilityStorageUniformBufferBlock16 || - cap == spv::CapabilityStorageUniform16) { - foundStorage = true; - break; - } - } - if (!foundStorage) { - if (containsType(typeId, OpTypeFloat, 16)) - addCapability(CapabilityFloat16); - if (containsType(typeId, OpTypeInt, 16)) - addCapability(CapabilityInt16); - } - } - if (containsType(typeId, OpTypeInt, 8)) { - bool foundStorage = false; - for (auto it = capabilities.begin(); it != capabilities.end(); ++it) { - spv::Capability cap = *it; - if (cap == spv::CapabilityStoragePushConstant8 || - cap == spv::CapabilityUniformAndStorageBuffer8BitAccess || - cap == spv::CapabilityStorageBuffer8BitAccess) { - foundStorage = true; - break; - } - } - if (!foundStorage) { - addCapability(CapabilityInt8); - } - } - break; - case OpExtInst: - switch (inst.getImmediateOperand(1)) { - case GLSLstd450Frexp: - case GLSLstd450FrexpStruct: - if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeInt, 16)) - addExtension(spv::E_SPV_AMD_gpu_shader_int16); - break; - case GLSLstd450InterpolateAtCentroid: - case GLSLstd450InterpolateAtSample: - case GLSLstd450InterpolateAtOffset: - if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeFloat, 16)) - addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - break; - default: - break; - } - break; - case OpAccessChain: - case OpPtrAccessChain: - if (isPointerType(typeId)) - break; - if (basicTypeOp == OpTypeInt) { - if (width == 16) - addCapability(CapabilityInt16); - else if (width == 8) - addCapability(CapabilityInt8); - } - break; - default: - if (basicTypeOp == OpTypeInt) { - if (width == 16) - addCapability(CapabilityInt16); - else if (width == 8) - addCapability(CapabilityInt8); - else if (width == 64) - addCapability(CapabilityInt64); - } else if (basicTypeOp == OpTypeFloat) { - if (width == 16) - addCapability(CapabilityFloat16); - else if (width == 64) - addCapability(CapabilityFloat64); - } - break; - } -} - -// Called for each instruction that resides in a block. -void Builder::postProcess(Instruction& inst) -{ - // Add capabilities based simply on the opcode. - switch (inst.getOpCode()) { - case OpExtInst: - switch (inst.getImmediateOperand(1)) { - case GLSLstd450InterpolateAtCentroid: - case GLSLstd450InterpolateAtSample: - case GLSLstd450InterpolateAtOffset: - addCapability(CapabilityInterpolationFunction); - break; - default: - break; - } - break; - case OpDPdxFine: - case OpDPdyFine: - case OpFwidthFine: - case OpDPdxCoarse: - case OpDPdyCoarse: - case OpFwidthCoarse: - addCapability(CapabilityDerivativeControl); - break; - - case OpImageQueryLod: - case OpImageQuerySize: - case OpImageQuerySizeLod: - case OpImageQuerySamples: - case OpImageQueryLevels: - addCapability(CapabilityImageQuery); - break; - - case OpGroupNonUniformPartitionNV: - addExtension(E_SPV_NV_shader_subgroup_partitioned); - addCapability(CapabilityGroupNonUniformPartitionedNV); - break; - - case OpLoad: - case OpStore: - { - // For any load/store to a PhysicalStorageBufferEXT, walk the accesschain - // index list to compute the misalignment. The pre-existing alignment value - // (set via Builder::AccessChain::alignment) only accounts for the base of - // the reference type and any scalar component selection in the accesschain, - // and this function computes the rest from the SPIR-V Offset decorations. - Instruction *accessChain = module.getInstruction(inst.getIdOperand(0)); - if (accessChain->getOpCode() == OpAccessChain) { - Instruction *base = module.getInstruction(accessChain->getIdOperand(0)); - // Get the type of the base of the access chain. It must be a pointer type. - Id typeId = base->getTypeId(); - Instruction *type = module.getInstruction(typeId); - assert(type->getOpCode() == OpTypePointer); - if (type->getImmediateOperand(0) != StorageClassPhysicalStorageBufferEXT) { - break; - } - // Get the pointee type. - typeId = type->getIdOperand(1); - type = module.getInstruction(typeId); - // Walk the index list for the access chain. For each index, find any - // misalignment that can apply when accessing the member/element via - // Offset/ArrayStride/MatrixStride decorations, and bitwise OR them all - // together. - int alignment = 0; - for (int i = 1; i < accessChain->getNumOperands(); ++i) { - Instruction *idx = module.getInstruction(accessChain->getIdOperand(i)); - if (type->getOpCode() == OpTypeStruct) { - assert(idx->getOpCode() == OpConstant); - unsigned int c = idx->getImmediateOperand(0); - - const auto function = [&](const std::unique_ptr& decoration) { - if (decoration.get()->getOpCode() == OpMemberDecorate && - decoration.get()->getIdOperand(0) == typeId && - decoration.get()->getImmediateOperand(1) == c && - (decoration.get()->getImmediateOperand(2) == DecorationOffset || - decoration.get()->getImmediateOperand(2) == DecorationMatrixStride)) { - alignment |= decoration.get()->getImmediateOperand(3); - } - }; - std::for_each(decorations.begin(), decorations.end(), function); - // get the next member type - typeId = type->getIdOperand(c); - type = module.getInstruction(typeId); - } else if (type->getOpCode() == OpTypeArray || - type->getOpCode() == OpTypeRuntimeArray) { - const auto function = [&](const std::unique_ptr& decoration) { - if (decoration.get()->getOpCode() == OpDecorate && - decoration.get()->getIdOperand(0) == typeId && - decoration.get()->getImmediateOperand(1) == DecorationArrayStride) { - alignment |= decoration.get()->getImmediateOperand(2); - } - }; - std::for_each(decorations.begin(), decorations.end(), function); - // Get the element type - typeId = type->getIdOperand(0); - type = module.getInstruction(typeId); - } else { - // Once we get to any non-aggregate type, we're done. - break; - } - } - assert(inst.getNumOperands() >= 3); - unsigned int memoryAccess = inst.getImmediateOperand((inst.getOpCode() == OpStore) ? 2 : 1); - assert(memoryAccess & MemoryAccessAlignedMask); - static_cast(memoryAccess); - // Compute the index of the alignment operand. - int alignmentIdx = 2; - if (inst.getOpCode() == OpStore) - alignmentIdx++; - // Merge new and old (mis)alignment - alignment |= inst.getImmediateOperand(alignmentIdx); - // Pick the LSB - alignment = alignment & ~(alignment & (alignment-1)); - // update the Aligned operand - inst.setImmediateOperand(alignmentIdx, alignment); - } - break; - } - - default: - break; - } - - // Checks based on type - if (inst.getTypeId() != NoType) - postProcessType(inst, inst.getTypeId()); - for (int op = 0; op < inst.getNumOperands(); ++op) { - if (inst.isIdOperand(op)) { - // In blocks, these are always result ids, but we are relying on - // getTypeId() to return NoType for things like OpLabel. - if (getTypeId(inst.getIdOperand(op)) != NoType) - postProcessType(inst, getTypeId(inst.getIdOperand(op))); - } - } -} - -// comment in header -void Builder::postProcessCFG() -{ - // reachableBlocks is the set of blockss reached via control flow, or which are - // unreachable continue targert or unreachable merge. - std::unordered_set reachableBlocks; - std::unordered_map headerForUnreachableContinue; - std::unordered_set unreachableMerges; - std::unordered_set unreachableDefinitions; - // Collect IDs defined in unreachable blocks. For each function, label the - // reachable blocks first. Then for each unreachable block, collect the - // result IDs of the instructions in it. - for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) { - Function* f = *fi; - Block* entry = f->getEntryBlock(); - inReadableOrder(entry, - [&reachableBlocks, &unreachableMerges, &headerForUnreachableContinue] - (Block* b, ReachReason why, Block* header) { - reachableBlocks.insert(b); - if (why == ReachDeadContinue) headerForUnreachableContinue[b] = header; - if (why == ReachDeadMerge) unreachableMerges.insert(b); - }); - for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) { - Block* b = *bi; - if (unreachableMerges.count(b) != 0 || headerForUnreachableContinue.count(b) != 0) { - auto ii = b->getInstructions().cbegin(); - ++ii; // Keep potential decorations on the label. - for (; ii != b->getInstructions().cend(); ++ii) - unreachableDefinitions.insert(ii->get()->getResultId()); - } else if (reachableBlocks.count(b) == 0) { - // The normal case for unreachable code. All definitions are considered dead. - for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ++ii) - unreachableDefinitions.insert(ii->get()->getResultId()); - } - } - } - - // Modify unreachable merge blocks and unreachable continue targets. - // Delete their contents. - for (auto mergeIter = unreachableMerges.begin(); mergeIter != unreachableMerges.end(); ++mergeIter) { - (*mergeIter)->rewriteAsCanonicalUnreachableMerge(); - } - for (auto continueIter = headerForUnreachableContinue.begin(); - continueIter != headerForUnreachableContinue.end(); - ++continueIter) { - Block* continue_target = continueIter->first; - Block* header = continueIter->second; - continue_target->rewriteAsCanonicalUnreachableContinue(header); - } - - // Remove unneeded decorations, for unreachable instructions - for (auto decorationIter = decorations.begin(); decorationIter != decorations.end();) { - Id decorationId = (*decorationIter)->getIdOperand(0); - if (unreachableDefinitions.count(decorationId) != 0) { - decorationIter = decorations.erase(decorationIter); - } else { - ++decorationIter; - } - } -} - -// comment in header -void Builder::postProcessFeatures() { - // Add per-instruction capabilities, extensions, etc., - - // Look for any 8/16 bit type in physical storage buffer class, and set the - // appropriate capability. This happens in createSpvVariable for other storage - // classes, but there isn't always a variable for physical storage buffer. - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - Instruction* type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) { - if (containsType(type->getIdOperand(1), OpTypeInt, 8)) { - addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - addCapability(spv::CapabilityStorageBuffer8BitAccess); - } - if (containsType(type->getIdOperand(1), OpTypeInt, 16) || - containsType(type->getIdOperand(1), OpTypeFloat, 16)) { - addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - addCapability(spv::CapabilityStorageBuffer16BitAccess); - } - } - } - - // process all block-contained instructions - for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) { - Function* f = *fi; - for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) { - Block* b = *bi; - for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++) - postProcess(*ii->get()); - - // For all local variables that contain pointers to PhysicalStorageBufferEXT, check whether - // there is an existing restrict/aliased decoration. If we don't find one, add Aliased as the - // default. - for (auto vi = b->getLocalVariables().cbegin(); vi != b->getLocalVariables().cend(); vi++) { - const Instruction& inst = *vi->get(); - Id resultId = inst.getResultId(); - if (containsPhysicalStorageBufferOrArray(getDerefTypeId(resultId))) { - bool foundDecoration = false; - const auto function = [&](const std::unique_ptr& decoration) { - if (decoration.get()->getIdOperand(0) == resultId && - decoration.get()->getOpCode() == OpDecorate && - (decoration.get()->getImmediateOperand(1) == spv::DecorationAliasedPointerEXT || - decoration.get()->getImmediateOperand(1) == spv::DecorationRestrictPointerEXT)) { - foundDecoration = true; - } - }; - std::for_each(decorations.begin(), decorations.end(), function); - if (!foundDecoration) { - addDecoration(resultId, spv::DecorationAliasedPointerEXT); - } - } - } - } - } - - // If any Vulkan memory model-specific functionality is used, update the - // OpMemoryModel to match. - if (capabilities.find(spv::CapabilityVulkanMemoryModelKHR) != capabilities.end()) { - memoryModel = spv::MemoryModelVulkanKHR; - addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); - } - - // Add Aliased decoration if there's more than one Workgroup Block variable. - if (capabilities.find(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR) != capabilities.end()) { - assert(entryPoints.size() == 1); - auto &ep = entryPoints[0]; - - std::vector workgroup_variables; - for (int i = 0; i < (int)ep->getNumOperands(); i++) { - if (!ep->isIdOperand(i)) - continue; - - const Id id = ep->getIdOperand(i); - const Instruction *instr = module.getInstruction(id); - if (instr->getOpCode() != spv::OpVariable) - continue; - - if (instr->getImmediateOperand(0) == spv::StorageClassWorkgroup) - workgroup_variables.push_back(id); - } - - if (workgroup_variables.size() > 1) { - for (size_t i = 0; i < workgroup_variables.size(); i++) - addDecoration(workgroup_variables[i], spv::DecorationAliased); - } - } -} - -// SPIR-V requires that any instruction consuming the result of an OpSampledImage -// be in the same block as the OpSampledImage instruction. This pass goes finds -// uses of OpSampledImage where that is not the case and duplicates the -// OpSampledImage to be immediately before the instruction that consumes it. -// The old OpSampledImage is left in place, potentially with no users. -void Builder::postProcessSamplers() -{ - // first, find all OpSampledImage instructions and store them in a map. - std::map sampledImageInstrs; - for (auto f: module.getFunctions()) { - for (auto b: f->getBlocks()) { - for (auto &i: b->getInstructions()) { - if (i->getOpCode() == spv::OpSampledImage) { - sampledImageInstrs[i->getResultId()] = i.get(); - } - } - } - } - // next find all uses of the given ids and rewrite them if needed. - for (auto f: module.getFunctions()) { - for (auto b: f->getBlocks()) { - auto &instrs = b->getInstructions(); - for (size_t idx = 0; idx < instrs.size(); idx++) { - Instruction *i = instrs[idx].get(); - for (int opnum = 0; opnum < i->getNumOperands(); opnum++) { - // Is this operand of the current instruction the result of an OpSampledImage? - if (i->isIdOperand(opnum) && - sampledImageInstrs.count(i->getIdOperand(opnum))) - { - Instruction *opSampImg = sampledImageInstrs[i->getIdOperand(opnum)]; - if (i->getBlock() != opSampImg->getBlock()) { - Instruction *newInstr = new Instruction(getUniqueId(), - opSampImg->getTypeId(), - spv::OpSampledImage); - newInstr->addIdOperand(opSampImg->getIdOperand(0)); - newInstr->addIdOperand(opSampImg->getIdOperand(1)); - newInstr->setBlock(b); - - // rewrite the user of the OpSampledImage to use the new instruction. - i->setIdOperand(opnum, newInstr->getResultId()); - // insert the new OpSampledImage right before the current instruction. - instrs.insert(instrs.begin() + idx, - std::unique_ptr(newInstr)); - idx++; - } - } - } - } - } - } -} - -// comment in header -void Builder::postProcess(bool compileOnly) -{ - // postProcessCFG needs an entrypoint to determine what is reachable, but if we are not creating an "executable" shader, we don't have an entrypoint - if (!compileOnly) - postProcessCFG(); - - postProcessFeatures(); - postProcessSamplers(); -} - -} // end spv namespace diff --git a/include/SPIRV/SpvTools.cpp b/include/SPIRV/SpvTools.cpp deleted file mode 100644 index 8cd03ef5..00000000 --- a/include/SPIRV/SpvTools.cpp +++ /dev/null @@ -1,314 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2018-2020 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Call into SPIRV-Tools to disassemble, validate, and optimize. -// - -#if ENABLE_OPT - -#include -#include - -#include "SpvTools.h" -#include "spirv-tools/optimizer.hpp" -#include "glslang/MachineIndependent/localintermediate.h" - -namespace glslang { - -// Translate glslang's view of target versioning to what SPIRV-Tools uses. -spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger) -{ - switch (spvVersion.vulkan) { - case glslang::EShTargetVulkan_1_0: - return spv_target_env::SPV_ENV_VULKAN_1_0; - case glslang::EShTargetVulkan_1_1: - switch (spvVersion.spv) { - case EShTargetSpv_1_0: - case EShTargetSpv_1_1: - case EShTargetSpv_1_2: - case EShTargetSpv_1_3: - return spv_target_env::SPV_ENV_VULKAN_1_1; - case EShTargetSpv_1_4: - return spv_target_env::SPV_ENV_VULKAN_1_1_SPIRV_1_4; - default: - logger->missingFunctionality("Target version for SPIRV-Tools validator"); - return spv_target_env::SPV_ENV_VULKAN_1_1; - } - case glslang::EShTargetVulkan_1_2: - return spv_target_env::SPV_ENV_VULKAN_1_2; - case glslang::EShTargetVulkan_1_3: - return spv_target_env::SPV_ENV_VULKAN_1_3; - default: - break; - } - - if (spvVersion.openGl > 0) - return spv_target_env::SPV_ENV_OPENGL_4_5; - - logger->missingFunctionality("Target version for SPIRV-Tools validator"); - return spv_target_env::SPV_ENV_UNIVERSAL_1_0; -} - -spv_target_env MapToSpirvToolsEnv(const glslang::TIntermediate& intermediate, spv::SpvBuildLogger* logger) -{ - return MapToSpirvToolsEnv(intermediate.getSpv(), logger); -} - -// Callback passed to spvtools::Optimizer::SetMessageConsumer -void OptimizerMesssageConsumer(spv_message_level_t level, const char *source, - const spv_position_t &position, const char *message) -{ - auto &out = std::cerr; - switch (level) - { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - out << "error: "; - break; - case SPV_MSG_WARNING: - out << "warning: "; - break; - case SPV_MSG_INFO: - case SPV_MSG_DEBUG: - out << "info: "; - break; - default: - break; - } - if (source) - { - out << source << ":"; - } - out << position.line << ":" << position.column << ":" << position.index << ":"; - if (message) - { - out << " " << message; - } - out << std::endl; -} - -// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment. -void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv) -{ - SpirvToolsDisassemble(out, spirv, spv_target_env::SPV_ENV_UNIVERSAL_1_3); -} - -// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment. -void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv, - spv_target_env requested_context) -{ - // disassemble - spv_context context = spvContextCreate(requested_context); - spv_text text; - spv_diagnostic diagnostic = nullptr; - spvBinaryToText(context, spirv.data(), spirv.size(), - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT, - &text, &diagnostic); - - // dump - if (diagnostic == nullptr) - out << text->str; - else - spvDiagnosticPrint(diagnostic); - - // teardown - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(context); -} - -// Apply the SPIRV-Tools validator to generated SPIR-V. -void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, bool prelegalization) -{ - // validate - spv_context context = spvContextCreate(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); - spv_const_binary_t binary = { spirv.data(), spirv.size() }; - spv_diagnostic diagnostic = nullptr; - spv_validator_options options = spvValidatorOptionsCreate(); - spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets()); - spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization); - spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); - spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); - spvValidateWithOptions(context, options, &binary, &diagnostic); - - // report - if (diagnostic != nullptr) { - logger->error("SPIRV-Tools Validation Errors"); - logger->error(diagnostic->error); - } - - // tear down - spvValidatorOptionsDestroy(options); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(context); -} - -// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process. -void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, const SpvOptions* options) -{ - spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger); - - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - // If debug (specifically source line info) is being generated, propagate - // line information into all SPIR-V instructions. This avoids loss of - // information when instructions are deleted or moved. Later, remove - // redundant information to minimize final SPRIR-V size. - if (options->stripDebugInfo) { - optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass()); - } - optimizer.RegisterPass(spvtools::CreateWrapOpKillPass()); - optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); - optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); - optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); - optimizer.RegisterPass(spvtools::CreateEliminateDeadFunctionsPass()); - optimizer.RegisterPass(spvtools::CreateScalarReplacementPass()); - optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); - optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); - optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); - optimizer.RegisterPass(spvtools::CreateSimplificationPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateVectorDCEPass()); - optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); - optimizer.RegisterPass(spvtools::CreateBlockMergePass()); - optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); - optimizer.RegisterPass(spvtools::CreateIfConversionPass()); - optimizer.RegisterPass(spvtools::CreateSimplificationPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateVectorDCEPass()); - optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); - optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass()); - if (options->optimizeSize) { - optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); - optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsSafePass()); - } - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateCFGCleanupPass()); - - spvtools::OptimizerOptions spvOptOptions; - if (options->optimizerAllowExpandedIDBound) - spvOptOptions.set_max_id_bound(0x3FFFFFFF); - optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); - spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); - - if (options->optimizerAllowExpandedIDBound) { - if (spirv.size() > 3 && spirv[3] > kDefaultMaxIdBound) { - spvtools::Optimizer optimizer2(target_env); - optimizer2.SetMessageConsumer(OptimizerMesssageConsumer); - optimizer2.RegisterPass(spvtools::CreateCompactIdsPass()); - optimizer2.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); - } - } -} - -bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, - spv::SpvBuildLogger*) -{ - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateAnalyzeLiveInputPass(live_locs, live_builtins)); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(target_env); - spvOptOptions.set_run_validator(false); - return optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -void SpirvToolsEliminateDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, - spv::SpvBuildLogger*) -{ - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateEliminateDeadOutputStoresPass(live_locs, live_builtins)); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass(false, true)); - optimizer.RegisterPass(spvtools::CreateEliminateDeadOutputComponentsPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass(false, true)); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(target_env); - spvOptOptions.set_run_validator(false); - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -void SpirvToolsEliminateDeadInputComponents(spv_target_env target_env, std::vector& spirv, - spv::SpvBuildLogger*) -{ - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(target_env); - spvOptOptions.set_run_validator(false); - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by -// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if -// optimization is disabled. -void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate, - std::vector& spirv, spv::SpvBuildLogger* logger) -{ - spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger); - - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass()); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); - spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -} // end namespace glslang - -#endif diff --git a/include/SPIRV/SpvTools.h b/include/SPIRV/SpvTools.h deleted file mode 100644 index 45585723..00000000 --- a/include/SPIRV/SpvTools.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Call into SPIRV-Tools to disassemble, validate, and optimize. -// - -#pragma once -#ifndef GLSLANG_SPV_TOOLS_H -#define GLSLANG_SPV_TOOLS_H - -#if ENABLE_OPT -#include -#include -#include -#include "spirv-tools/libspirv.h" -#endif - -#include "glslang/MachineIndependent/Versions.h" -#include "glslang/Include/visibility.h" -#include "GlslangToSpv.h" -#include "Logger.h" - -namespace glslang { - -#if ENABLE_OPT - -class TIntermediate; - -// Translate glslang's view of target versioning to what SPIRV-Tools uses. -GLSLANG_EXPORT spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger); -GLSLANG_EXPORT spv_target_env MapToSpirvToolsEnv(const glslang::TIntermediate& intermediate, spv::SpvBuildLogger* logger); - -// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment. -GLSLANG_EXPORT void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); - -// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment. -GLSLANG_EXPORT void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv, - spv_target_env requested_context); - -// Apply the SPIRV-Tools validator to generated SPIR-V. -GLSLANG_EXPORT void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger*, bool prelegalization); - -// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process. -GLSLANG_EXPORT void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger*, const SpvOptions*); - -// Apply the SPIRV-Tools EliminateDeadInputComponents pass to generated SPIR-V. Put result in |spirv|. -GLSLANG_EXPORT void SpirvToolsEliminateDeadInputComponents(spv_target_env target_env, std::vector& spirv, - spv::SpvBuildLogger*); - -// Apply the SPIRV-Tools AnalyzeDeadOutputStores pass to generated SPIR-V. Put result in |live_locs|. -// Return true if the result is valid. -GLSLANG_EXPORT bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, - spv::SpvBuildLogger*); - -// Apply the SPIRV-Tools EliminateDeadOutputStores and AggressiveDeadCodeElimination passes to generated SPIR-V using -// |live_locs|. Put result in |spirv|. -GLSLANG_EXPORT void SpirvToolsEliminateDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, - spv::SpvBuildLogger*); - -// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by -// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if -// optimization is disabled. -GLSLANG_EXPORT void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate, - std::vector& spirv, spv::SpvBuildLogger*); - -#endif - -} // end namespace glslang - -#endif // GLSLANG_SPV_TOOLS_H diff --git a/include/SPIRV/bitutils.h b/include/SPIRV/bitutils.h deleted file mode 100644 index 22e44cec..00000000 --- a/include/SPIRV/bitutils.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef LIBSPIRV_UTIL_BITUTILS_H_ -#define LIBSPIRV_UTIL_BITUTILS_H_ - -#include -#include - -namespace spvutils { - -// Performs a bitwise copy of source to the destination type Dest. -template -Dest BitwiseCast(Src source) { - Dest dest; - static_assert(sizeof(source) == sizeof(dest), - "BitwiseCast: Source and destination must have the same size"); - std::memcpy(static_cast(&dest), &source, sizeof(dest)); - return dest; -} - -// SetBits returns an integer of type with bits set -// for position through , counting from the least -// significant bit. In particular when Num == 0, no positions are set to 1. -// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, -// a bit that will not fit in the underlying type is set. -template -struct SetBits { - static_assert(First < sizeof(T) * 8, - "Tried to set a bit that is shifted too far."); - const static T get = (T(1) << First) | SetBits::get; -}; - -template -struct SetBits { - const static T get = T(0); -}; - -// This is all compile-time so we can put our tests right here. -static_assert(SetBits::get == uint32_t(0x00000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x00000001), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x80000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x00000006), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xc0000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x7FFFFFFF), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xFFFFFFFF), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xFFFF0000), - "SetBits failed"); - -static_assert(SetBits::get == uint64_t(0x0000000000000001LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x8000000000000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0xc000000000000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x0000000080000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), - "SetBits failed"); - -} // namespace spvutils - -#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/include/SPIRV/disassemble.cpp b/include/SPIRV/disassemble.cpp deleted file mode 100644 index 606e8899..00000000 --- a/include/SPIRV/disassemble.cpp +++ /dev/null @@ -1,864 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "disassemble.h" -#include "doc.h" - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.std.450.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "NonSemanticShaderDebugInfo100.h" - #include "GLSL.ext.QCOM.h" - } -} -const char* GlslStd450DebugNames[spv::GLSLstd450Count]; - -namespace spv { - -static const char* GLSLextAMDGetDebugNames(const char*, unsigned); -static const char* GLSLextNVGetDebugNames(const char*, unsigned); -static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned); - -static void Kill(std::ostream& out, const char* message) -{ - out << std::endl << "Disassembly failed: " << message << std::endl; - exit(1); -} - -// used to identify the extended instruction library imported when printing -enum ExtInstSet { - GLSL450Inst, - GLSLextAMDInst, - GLSLextNVInst, - OpenCLExtInst, - NonSemanticDebugPrintfExtInst, - NonSemanticDebugBreakExtInst, - NonSemanticShaderDebugInfo100 -}; - -// Container class for a single instance of a SPIR-V stream, with methods for disassembly. -class SpirvStream { -public: - SpirvStream(std::ostream& out, const std::vector& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { } - virtual ~SpirvStream() { } - - void validate(); - void processInstructions(); - -protected: - SpirvStream(const SpirvStream&); - SpirvStream& operator=(const SpirvStream&); - Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; } - - // Output methods - void outputIndent(); - void formatId(Id id, std::stringstream&); - void outputResultId(Id id); - void outputTypeId(Id id); - void outputId(Id id); - void outputMask(OperandClass operandClass, unsigned mask); - void disassembleImmediates(int numOperands); - void disassembleIds(int numOperands); - std::pair decodeString(); - int disassembleString(); - void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands); - - // Data - std::ostream& out; // where to write the disassembly - const std::vector& stream; // the actual word stream - int size; // the size of the word stream - int word; // the next word of the stream to read - - // map each to the instruction that created it - Id bound; - std::vector idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter) - - std::vector idDescriptor; // the best text string known for explaining the - - // schema - unsigned int schema; - - // stack of structured-merge points - std::stack nestedControl; - Id nextNestedControl; // need a slight delay for when we are nested -}; - -void SpirvStream::validate() -{ - size = (int)stream.size(); - if (size < 4) - Kill(out, "stream is too short"); - - // Magic number - if (stream[word++] != MagicNumber) { - out << "Bad magic number"; - return; - } - - // Version - out << "// Module Version " << std::hex << stream[word++] << std::endl; - - // Generator's magic number - out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl; - - // Result bound - bound = stream[word++]; - idInstruction.resize(bound); - idDescriptor.resize(bound); - out << "// Id's are bound by " << bound << std::endl; - out << std::endl; - - // Reserved schema, must be 0 for now - schema = stream[word++]; - if (schema != 0) - Kill(out, "bad schema, must be 0"); -} - -// Loop over all the instructions, in order, processing each. -// Boiler plate for each is handled here directly, the rest is dispatched. -void SpirvStream::processInstructions() -{ - // Instructions - while (word < size) { - int instructionStart = word; - - // Instruction wordCount and opcode - unsigned int firstWord = stream[word]; - unsigned wordCount = firstWord >> WordCountShift; - Op opCode = (Op)(firstWord & OpCodeMask); - int nextInst = word + wordCount; - ++word; - - // Presence of full instruction - if (nextInst > size) - Kill(out, "stream instruction terminated too early"); - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - // Type - Id typeId = 0; - if (InstructionDesc[opCode].hasType()) { - typeId = stream[word++]; - --numOperands; - } - - // Result - Id resultId = 0; - if (InstructionDesc[opCode].hasResult()) { - resultId = stream[word++]; - --numOperands; - - // save instruction for future reference - idInstruction[resultId] = instructionStart; - } - - outputResultId(resultId); - outputTypeId(typeId); - outputIndent(); - - // Hand off the Op and all its operands - disassembleInstruction(resultId, typeId, opCode, numOperands); - if (word != nextInst) { - out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart; - word = nextInst; - } - out << std::endl; - } -} - -void SpirvStream::outputIndent() -{ - for (int i = 0; i < (int)nestedControl.size(); ++i) - out << " "; -} - -void SpirvStream::formatId(Id id, std::stringstream& idStream) -{ - if (id != 0) { - // On instructions with no IDs, this is called with "0", which does not - // have to be within ID bounds on null shaders. - if (id >= bound) - Kill(out, "Bad "); - - idStream << id; - if (idDescriptor[id].size() > 0) - idStream << "(" << idDescriptor[id] << ")"; - } -} - -void SpirvStream::outputResultId(Id id) -{ - const int width = 16; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str(); - if (id != 0) - out << ":"; - else - out << " "; - - if (nestedControl.size() && id == nestedControl.top()) - nestedControl.pop(); -} - -void SpirvStream::outputTypeId(Id id) -{ - const int width = 12; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str() << " "; -} - -void SpirvStream::outputId(Id id) -{ - if (id >= bound) - Kill(out, "Bad "); - - out << id; - if (idDescriptor[id].size() > 0) - out << "(" << idDescriptor[id] << ")"; -} - -void SpirvStream::outputMask(OperandClass operandClass, unsigned mask) -{ - if (mask == 0) - out << "None"; - else { - for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) { - if (mask & (1 << m)) - out << OperandClassParams[operandClass].getName(m) << " "; - } - } -} - -void SpirvStream::disassembleImmediates(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - out << stream[word++]; - if (i < numOperands - 1) - out << " "; - } -} - -void SpirvStream::disassembleIds(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - outputId(stream[word++]); - if (i < numOperands - 1) - out << " "; - } -} - -// decode string from words at current position (non-consuming) -std::pair SpirvStream::decodeString() -{ - std::string res; - int wordPos = word; - char c; - bool done = false; - - do { - unsigned int content = stream[wordPos]; - for (int charCount = 0; charCount < 4; ++charCount) { - c = content & 0xff; - content >>= 8; - if (c == '\0') { - done = true; - break; - } - res += c; - } - ++wordPos; - } while(! done); - - return std::make_pair(wordPos - word, res); -} - -// return the number of operands consumed by the string -int SpirvStream::disassembleString() -{ - out << " \""; - - std::pair decoderes = decodeString(); - - out << decoderes.second; - out << "\""; - - word += decoderes.first; - - return decoderes.first; -} - -static uint32_t popcount(uint32_t mask) -{ - uint32_t count = 0; - while (mask) { - if (mask & 1) { - count++; - } - mask >>= 1; - } - return count; -} - -void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands) -{ - // Process the opcode - - out << (OpcodeString(opCode) + 2); // leave out the "Op" - - if (opCode == OpLoopMerge || opCode == OpSelectionMerge) - nextNestedControl = stream[word]; - else if (opCode == OpBranchConditional || opCode == OpSwitch) { - if (nextNestedControl) { - nestedControl.push(nextNestedControl); - nextNestedControl = 0; - } - } else if (opCode == OpExtInstImport) { - idDescriptor[resultId] = decodeString().second; - } - else { - if (resultId != 0 && idDescriptor[resultId].size() == 0) { - switch (opCode) { - case OpTypeInt: - switch (stream[word]) { - case 8: idDescriptor[resultId] = "int8_t"; break; - case 16: idDescriptor[resultId] = "int16_t"; break; - default: assert(0); [[fallthrough]]; - case 32: idDescriptor[resultId] = "int"; break; - case 64: idDescriptor[resultId] = "int64_t"; break; - } - break; - case OpTypeFloat: - switch (stream[word]) { - case 16: idDescriptor[resultId] = "float16_t"; break; - default: assert(0); [[fallthrough]]; - case 32: idDescriptor[resultId] = "float"; break; - case 64: idDescriptor[resultId] = "float64_t"; break; - } - break; - case OpTypeBool: - idDescriptor[resultId] = "bool"; - break; - case OpTypeStruct: - idDescriptor[resultId] = "struct"; - break; - case OpTypePointer: - idDescriptor[resultId] = "ptr"; - break; - case OpTypeVector: - if (idDescriptor[stream[word]].size() > 0) { - idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1); - if (strstr(idDescriptor[stream[word]].c_str(), "8")) { - idDescriptor[resultId].append("8"); - } - if (strstr(idDescriptor[stream[word]].c_str(), "16")) { - idDescriptor[resultId].append("16"); - } - if (strstr(idDescriptor[stream[word]].c_str(), "64")) { - idDescriptor[resultId].append("64"); - } - } - idDescriptor[resultId].append("vec"); - switch (stream[word + 1]) { - case 2: idDescriptor[resultId].append("2"); break; - case 3: idDescriptor[resultId].append("3"); break; - case 4: idDescriptor[resultId].append("4"); break; - case 8: idDescriptor[resultId].append("8"); break; - case 16: idDescriptor[resultId].append("16"); break; - case 32: idDescriptor[resultId].append("32"); break; - default: break; - } - break; - default: - break; - } - } - } - - // Process the operands. Note, a new context-dependent set could be - // swapped in mid-traversal. - - // Handle images specially, so can put out helpful strings. - if (opCode == OpTypeImage) { - out << " "; - disassembleIds(1); - out << " " << DimensionString((Dim)stream[word++]); - out << (stream[word++] != 0 ? " depth" : ""); - out << (stream[word++] != 0 ? " array" : ""); - out << (stream[word++] != 0 ? " multi-sampled" : ""); - switch (stream[word++]) { - case 0: out << " runtime"; break; - case 1: out << " sampled"; break; - case 2: out << " nonsampled"; break; - } - out << " format:" << ImageFormatString((ImageFormat)stream[word++]); - - if (numOperands == 8) { - out << " " << AccessQualifierString(stream[word++]); - } - return; - } - - // Handle all the parameterized operands - for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) { - out << " "; - OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op); - switch (operandClass) { - case OperandId: - case OperandScope: - case OperandMemorySemantics: - disassembleIds(1); - --numOperands; - // Get names for printing "(XXX)" for readability, *after* this id - if (opCode == OpName) - idDescriptor[stream[word - 1]] = decodeString().second; - break; - case OperandVariableIds: - disassembleIds(numOperands); - return; - case OperandImageOperands: - outputMask(OperandImageOperands, stream[word++]); - --numOperands; - disassembleIds(numOperands); - return; - case OperandOptionalLiteral: - case OperandVariableLiterals: - if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) || - (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) { - out << BuiltInString(stream[word++]); - --numOperands; - ++op; - } - disassembleImmediates(numOperands); - return; - case OperandVariableIdLiteral: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " Type "; - disassembleIds(1); - out << ", member "; - disassembleImmediates(1); - numOperands -= 2; - } - return; - case OperandVariableLiteralId: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " case "; - disassembleImmediates(1); - out << ": "; - disassembleIds(1); - numOperands -= 2; - } - return; - case OperandLiteralNumber: - disassembleImmediates(1); - --numOperands; - if (opCode == OpExtInst) { - ExtInstSet extInstSet = GLSL450Inst; - const char* name = idDescriptor[stream[word - 2]].c_str(); - if (strcmp("OpenCL.std", name) == 0) { - extInstSet = OpenCLExtInst; - } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) { - extInstSet = OpenCLExtInst; - } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) { - extInstSet = NonSemanticDebugPrintfExtInst; - } else if (strcmp("NonSemantic.DebugBreak", name) == 0) { - extInstSet = NonSemanticDebugBreakExtInst; - } else if (strcmp("NonSemantic.Shader.DebugInfo.100", name) == 0) { - extInstSet = NonSemanticShaderDebugInfo100; - } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 || - strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) { - extInstSet = GLSLextAMDInst; - } else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 || - strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 || - strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 || - strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 || - strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 || - strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) { - extInstSet = GLSLextNVInst; - } - unsigned entrypoint = stream[word - 1]; - if (extInstSet == GLSL450Inst) { - if (entrypoint < GLSLstd450Count) { - out << "(" << GlslStd450DebugNames[entrypoint] << ")"; - } - } else if (extInstSet == GLSLextAMDInst) { - out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")"; - } - else if (extInstSet == GLSLextNVInst) { - out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")"; - } else if (extInstSet == NonSemanticDebugPrintfExtInst) { - out << "(DebugPrintf)"; - } else if (extInstSet == NonSemanticDebugBreakExtInst) { - out << "(DebugBreak)"; - } else if (extInstSet == NonSemanticShaderDebugInfo100) { - out << "(" << NonSemanticShaderDebugInfo100GetDebugNames(entrypoint) << ")"; - } - } - break; - case OperandOptionalLiteralString: - case OperandLiteralString: - numOperands -= disassembleString(); - break; - case OperandVariableLiteralStrings: - while (numOperands > 0) - numOperands -= disassembleString(); - return; - case OperandMemoryAccess: - { - outputMask(OperandMemoryAccess, stream[word++]); - --numOperands; - // Put a space after "None" if there are any remaining operands - if (numOperands && stream[word-1] == 0) { - out << " "; - } - uint32_t mask = stream[word-1]; - // Aligned is the only memory access operand that uses an immediate - // value, and it is also the first operand that uses a value at all. - if (mask & MemoryAccessAlignedMask) { - disassembleImmediates(1); - numOperands--; - if (numOperands) - out << " "; - } - - uint32_t bitCount = popcount(mask & (MemoryAccessMakePointerAvailableMask | MemoryAccessMakePointerVisibleMask)); - disassembleIds(bitCount); - numOperands -= bitCount; - } - break; - case OperandTensorAddressingOperands: - { - outputMask(OperandTensorAddressingOperands, stream[word++]); - --numOperands; - // Put a space after "None" if there are any remaining operands - if (numOperands && stream[word-1] == 0) { - out << " "; - } - uint32_t bitCount = popcount(stream[word-1]); - disassembleIds(bitCount); - numOperands -= bitCount; - } - break; - default: - assert(operandClass >= OperandSource && operandClass < OperandOpcode); - - if (OperandClassParams[operandClass].bitmask) - outputMask(operandClass, stream[word++]); - else - out << OperandClassParams[operandClass].getName(stream[word++]); - --numOperands; - - break; - } - } - - return; -} - -static void GLSLstd450GetDebugNames(const char** names) -{ - for (int i = 0; i < GLSLstd450Count; ++i) - names[i] = "Unknown"; - - names[GLSLstd450Round] = "Round"; - names[GLSLstd450RoundEven] = "RoundEven"; - names[GLSLstd450Trunc] = "Trunc"; - names[GLSLstd450FAbs] = "FAbs"; - names[GLSLstd450SAbs] = "SAbs"; - names[GLSLstd450FSign] = "FSign"; - names[GLSLstd450SSign] = "SSign"; - names[GLSLstd450Floor] = "Floor"; - names[GLSLstd450Ceil] = "Ceil"; - names[GLSLstd450Fract] = "Fract"; - names[GLSLstd450Radians] = "Radians"; - names[GLSLstd450Degrees] = "Degrees"; - names[GLSLstd450Sin] = "Sin"; - names[GLSLstd450Cos] = "Cos"; - names[GLSLstd450Tan] = "Tan"; - names[GLSLstd450Asin] = "Asin"; - names[GLSLstd450Acos] = "Acos"; - names[GLSLstd450Atan] = "Atan"; - names[GLSLstd450Sinh] = "Sinh"; - names[GLSLstd450Cosh] = "Cosh"; - names[GLSLstd450Tanh] = "Tanh"; - names[GLSLstd450Asinh] = "Asinh"; - names[GLSLstd450Acosh] = "Acosh"; - names[GLSLstd450Atanh] = "Atanh"; - names[GLSLstd450Atan2] = "Atan2"; - names[GLSLstd450Pow] = "Pow"; - names[GLSLstd450Exp] = "Exp"; - names[GLSLstd450Log] = "Log"; - names[GLSLstd450Exp2] = "Exp2"; - names[GLSLstd450Log2] = "Log2"; - names[GLSLstd450Sqrt] = "Sqrt"; - names[GLSLstd450InverseSqrt] = "InverseSqrt"; - names[GLSLstd450Determinant] = "Determinant"; - names[GLSLstd450MatrixInverse] = "MatrixInverse"; - names[GLSLstd450Modf] = "Modf"; - names[GLSLstd450ModfStruct] = "ModfStruct"; - names[GLSLstd450FMin] = "FMin"; - names[GLSLstd450SMin] = "SMin"; - names[GLSLstd450UMin] = "UMin"; - names[GLSLstd450FMax] = "FMax"; - names[GLSLstd450SMax] = "SMax"; - names[GLSLstd450UMax] = "UMax"; - names[GLSLstd450FClamp] = "FClamp"; - names[GLSLstd450SClamp] = "SClamp"; - names[GLSLstd450UClamp] = "UClamp"; - names[GLSLstd450FMix] = "FMix"; - names[GLSLstd450Step] = "Step"; - names[GLSLstd450SmoothStep] = "SmoothStep"; - names[GLSLstd450Fma] = "Fma"; - names[GLSLstd450Frexp] = "Frexp"; - names[GLSLstd450FrexpStruct] = "FrexpStruct"; - names[GLSLstd450Ldexp] = "Ldexp"; - names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8"; - names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8"; - names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16"; - names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16"; - names[GLSLstd450PackHalf2x16] = "PackHalf2x16"; - names[GLSLstd450PackDouble2x32] = "PackDouble2x32"; - names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16"; - names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16"; - names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16"; - names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8"; - names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8"; - names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32"; - names[GLSLstd450Length] = "Length"; - names[GLSLstd450Distance] = "Distance"; - names[GLSLstd450Cross] = "Cross"; - names[GLSLstd450Normalize] = "Normalize"; - names[GLSLstd450FaceForward] = "FaceForward"; - names[GLSLstd450Reflect] = "Reflect"; - names[GLSLstd450Refract] = "Refract"; - names[GLSLstd450FindILsb] = "FindILsb"; - names[GLSLstd450FindSMsb] = "FindSMsb"; - names[GLSLstd450FindUMsb] = "FindUMsb"; - names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid"; - names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample"; - names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset"; - names[GLSLstd450NMin] = "NMin"; - names[GLSLstd450NMax] = "NMax"; - names[GLSLstd450NClamp] = "NClamp"; -} - -static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) { - switch (entrypoint) { - case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD"; - case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD"; - case WriteInvocationAMD: return "WriteInvocationAMD"; - case MbcntAMD: return "MbcntAMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) { - switch (entrypoint) { - case FMin3AMD: return "FMin3AMD"; - case UMin3AMD: return "UMin3AMD"; - case SMin3AMD: return "SMin3AMD"; - case FMax3AMD: return "FMax3AMD"; - case UMax3AMD: return "UMax3AMD"; - case SMax3AMD: return "SMax3AMD"; - case FMid3AMD: return "FMid3AMD"; - case UMid3AMD: return "UMid3AMD"; - case SMid3AMD: return "SMid3AMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) { - switch (entrypoint) { - case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD"; - default: return "Bad"; - } - } - else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) { - switch (entrypoint) { - case CubeFaceIndexAMD: return "CubeFaceIndexAMD"; - case CubeFaceCoordAMD: return "CubeFaceCoordAMD"; - case TimeAMD: return "TimeAMD"; - default: - break; - } - } - - return "Bad"; -} - -static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 || - strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 || - strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 || - strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 || - strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 || - strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 || - strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 || - strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) { - switch (entrypoint) { - // NV builtins - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case BuiltInBaryCoordNV: return "BaryCoordNV"; - case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; - case BuiltInTaskCountNV: return "TaskCountNV"; - case BuiltInPrimitiveCountNV: return "PrimitiveCountNV"; - case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV"; - case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV"; - case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV"; - case BuiltInLayerPerViewNV: return "LayerPerViewNV"; - case BuiltInMeshViewCountNV: return "MeshViewCountNV"; - case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV"; - - // NV Capabilities - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV"; - case CapabilityMeshShadingNV: return "MeshShadingNV"; - case CapabilityImageFootprintNV: return "ImageFootprintNV"; - case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV"; - - // NV Decorations - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; - case DecorationPerVertexNV: return "PerVertexNV"; - case DecorationPerPrimitiveNV: return "PerPrimitiveNV"; - case DecorationPerViewNV: return "PerViewNV"; - case DecorationPerTaskNV: return "PerTaskNV"; - - default: return "Bad"; - } - } - return "Bad"; -} - -static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned entrypoint) -{ - switch (entrypoint) { - case NonSemanticShaderDebugInfo100DebugInfoNone: return "DebugInfoNone"; - case NonSemanticShaderDebugInfo100DebugCompilationUnit: return "DebugCompilationUnit"; - case NonSemanticShaderDebugInfo100DebugTypeBasic: return "DebugTypeBasic"; - case NonSemanticShaderDebugInfo100DebugTypePointer: return "DebugTypePointer"; - case NonSemanticShaderDebugInfo100DebugTypeQualifier: return "DebugTypeQualifier"; - case NonSemanticShaderDebugInfo100DebugTypeArray: return "DebugTypeArray"; - case NonSemanticShaderDebugInfo100DebugTypeVector: return "DebugTypeVector"; - case NonSemanticShaderDebugInfo100DebugTypedef: return "DebugTypedef"; - case NonSemanticShaderDebugInfo100DebugTypeFunction: return "DebugTypeFunction"; - case NonSemanticShaderDebugInfo100DebugTypeEnum: return "DebugTypeEnum"; - case NonSemanticShaderDebugInfo100DebugTypeComposite: return "DebugTypeComposite"; - case NonSemanticShaderDebugInfo100DebugTypeMember: return "DebugTypeMember"; - case NonSemanticShaderDebugInfo100DebugTypeInheritance: return "DebugTypeInheritance"; - case NonSemanticShaderDebugInfo100DebugTypePtrToMember: return "DebugTypePtrToMember"; - case NonSemanticShaderDebugInfo100DebugTypeTemplate: return "DebugTypeTemplate"; - case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter: return "DebugTypeTemplateParameter"; - case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter: return "DebugTypeTemplateTemplateParameter"; - case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack: return "DebugTypeTemplateParameterPack"; - case NonSemanticShaderDebugInfo100DebugGlobalVariable: return "DebugGlobalVariable"; - case NonSemanticShaderDebugInfo100DebugFunctionDeclaration: return "DebugFunctionDeclaration"; - case NonSemanticShaderDebugInfo100DebugFunction: return "DebugFunction"; - case NonSemanticShaderDebugInfo100DebugLexicalBlock: return "DebugLexicalBlock"; - case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator: return "DebugLexicalBlockDiscriminator"; - case NonSemanticShaderDebugInfo100DebugScope: return "DebugScope"; - case NonSemanticShaderDebugInfo100DebugNoScope: return "DebugNoScope"; - case NonSemanticShaderDebugInfo100DebugInlinedAt: return "DebugInlinedAt"; - case NonSemanticShaderDebugInfo100DebugLocalVariable: return "DebugLocalVariable"; - case NonSemanticShaderDebugInfo100DebugInlinedVariable: return "DebugInlinedVariable"; - case NonSemanticShaderDebugInfo100DebugDeclare: return "DebugDeclare"; - case NonSemanticShaderDebugInfo100DebugValue: return "DebugValue"; - case NonSemanticShaderDebugInfo100DebugOperation: return "DebugOperation"; - case NonSemanticShaderDebugInfo100DebugExpression: return "DebugExpression"; - case NonSemanticShaderDebugInfo100DebugMacroDef: return "DebugMacroDef"; - case NonSemanticShaderDebugInfo100DebugMacroUndef: return "DebugMacroUndef"; - case NonSemanticShaderDebugInfo100DebugImportedEntity: return "DebugImportedEntity"; - case NonSemanticShaderDebugInfo100DebugSource: return "DebugSource"; - case NonSemanticShaderDebugInfo100DebugFunctionDefinition: return "DebugFunctionDefinition"; - case NonSemanticShaderDebugInfo100DebugSourceContinued: return "DebugSourceContinued"; - case NonSemanticShaderDebugInfo100DebugLine: return "DebugLine"; - case NonSemanticShaderDebugInfo100DebugNoLine: return "DebugNoLine"; - case NonSemanticShaderDebugInfo100DebugBuildIdentifier: return "DebugBuildIdentifier"; - case NonSemanticShaderDebugInfo100DebugStoragePath: return "DebugStoragePath"; - case NonSemanticShaderDebugInfo100DebugEntryPoint: return "DebugEntryPoint"; - case NonSemanticShaderDebugInfo100DebugTypeMatrix: return "DebugTypeMatrix"; - default: return "Bad"; - } - - return "Bad"; -} - -void Disassemble(std::ostream& out, const std::vector& stream) -{ - SpirvStream SpirvStream(out, stream); - spv::Parameterize(); - GLSLstd450GetDebugNames(GlslStd450DebugNames); - SpirvStream.validate(); - SpirvStream.processInstructions(); -} - -} // end namespace spv diff --git a/include/SPIRV/disassemble.h b/include/SPIRV/disassemble.h deleted file mode 100644 index 3bded14f..00000000 --- a/include/SPIRV/disassemble.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#pragma once -#ifndef disassembler_H -#define disassembler_H - -#include -#include - -#include "glslang/Include/visibility.h" - -namespace spv { - - // disassemble with glslang custom disassembler - GLSLANG_EXPORT void Disassemble(std::ostream& out, const std::vector&); - -} // end namespace spv - -#endif // disassembler_H diff --git a/include/SPIRV/doc.cpp b/include/SPIRV/doc.cpp deleted file mode 100644 index dce8a71a..00000000 --- a/include/SPIRV/doc.cpp +++ /dev/null @@ -1,3598 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2022-2024 Arm Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// 1) Programmatically fill in instruction/operand information. -// This can be used for disassembly, printing documentation, etc. -// -// 2) Print documentation from this parameterization. -// - -#include "doc.h" - -#include -#include -#include -#include - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "GLSL.ext.QCOM.h" - } -} - -namespace spv { - -// -// Whole set of functions that translate enumerants to their text strings for -// the specification (or their sanitized versions for auto-generating the -// spirv headers. -// -// Also, for masks the ceilings are declared next to these, to help keep them in sync. -// Ceilings should be -// - one more than the maximum value an enumerant takes on, for non-mask enumerants -// (for non-sparse enums, this is the number of enumerants) -// - the number of bits consumed by the set of masks -// (for non-sparse mask enums, this is the number of enumerants) -// - -const char* SourceString(int source) -{ - switch (source) { - case 0: return "Unknown"; - case 1: return "ESSL"; - case 2: return "GLSL"; - case 3: return "OpenCL_C"; - case 4: return "OpenCL_CPP"; - case 5: return "HLSL"; - - default: return "Bad"; - } -} - -const char* ExecutionModelString(int model) -{ - switch (model) { - case 0: return "Vertex"; - case 1: return "TessellationControl"; - case 2: return "TessellationEvaluation"; - case 3: return "Geometry"; - case 4: return "Fragment"; - case 5: return "GLCompute"; - case 6: return "Kernel"; - case ExecutionModelTaskNV: return "TaskNV"; - case ExecutionModelMeshNV: return "MeshNV"; - case ExecutionModelTaskEXT: return "TaskEXT"; - case ExecutionModelMeshEXT: return "MeshEXT"; - - default: return "Bad"; - - case ExecutionModelRayGenerationKHR: return "RayGenerationKHR"; - case ExecutionModelIntersectionKHR: return "IntersectionKHR"; - case ExecutionModelAnyHitKHR: return "AnyHitKHR"; - case ExecutionModelClosestHitKHR: return "ClosestHitKHR"; - case ExecutionModelMissKHR: return "MissKHR"; - case ExecutionModelCallableKHR: return "CallableKHR"; - } -} - -const char* AddressingString(int addr) -{ - switch (addr) { - case 0: return "Logical"; - case 1: return "Physical32"; - case 2: return "Physical64"; - - case AddressingModelPhysicalStorageBuffer64EXT: return "PhysicalStorageBuffer64EXT"; - - default: return "Bad"; - } -} - -const char* MemoryString(int mem) -{ - switch (mem) { - case MemoryModelSimple: return "Simple"; - case MemoryModelGLSL450: return "GLSL450"; - case MemoryModelOpenCL: return "OpenCL"; - case MemoryModelVulkanKHR: return "VulkanKHR"; - - default: return "Bad"; - } -} - -const int ExecutionModeCeiling = 40; - -const char* ExecutionModeString(int mode) -{ - switch (mode) { - case 0: return "Invocations"; - case 1: return "SpacingEqual"; - case 2: return "SpacingFractionalEven"; - case 3: return "SpacingFractionalOdd"; - case 4: return "VertexOrderCw"; - case 5: return "VertexOrderCcw"; - case 6: return "PixelCenterInteger"; - case 7: return "OriginUpperLeft"; - case 8: return "OriginLowerLeft"; - case 9: return "EarlyFragmentTests"; - case 10: return "PointMode"; - case 11: return "Xfb"; - case 12: return "DepthReplacing"; - case 13: return "Bad"; - case 14: return "DepthGreater"; - case 15: return "DepthLess"; - case 16: return "DepthUnchanged"; - case 17: return "LocalSize"; - case 18: return "LocalSizeHint"; - case 19: return "InputPoints"; - case 20: return "InputLines"; - case 21: return "InputLinesAdjacency"; - case 22: return "Triangles"; - case 23: return "InputTrianglesAdjacency"; - case 24: return "Quads"; - case 25: return "Isolines"; - case 26: return "OutputVertices"; - case 27: return "OutputPoints"; - case 28: return "OutputLineStrip"; - case 29: return "OutputTriangleStrip"; - case 30: return "VecTypeHint"; - case 31: return "ContractionOff"; - case 32: return "Bad"; - - case ExecutionModeInitializer: return "Initializer"; - case ExecutionModeFinalizer: return "Finalizer"; - case ExecutionModeSubgroupSize: return "SubgroupSize"; - case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup"; - case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId"; - case ExecutionModeLocalSizeId: return "LocalSizeId"; - case ExecutionModeLocalSizeHintId: return "LocalSizeHintId"; - - case ExecutionModePostDepthCoverage: return "PostDepthCoverage"; - case ExecutionModeDenormPreserve: return "DenormPreserve"; - case ExecutionModeDenormFlushToZero: return "DenormFlushToZero"; - case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; - case ExecutionModeRoundingModeRTE: return "RoundingModeRTE"; - case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ"; - case ExecutionModeEarlyAndLateFragmentTestsAMD: return "EarlyAndLateFragmentTestsAMD"; - case ExecutionModeStencilRefUnchangedFrontAMD: return "StencilRefUnchangedFrontAMD"; - case ExecutionModeStencilRefLessFrontAMD: return "StencilRefLessFrontAMD"; - case ExecutionModeStencilRefGreaterBackAMD: return "StencilRefGreaterBackAMD"; - case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT"; - case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow"; - case ExecutionModeMaximallyReconvergesKHR: return "MaximallyReconverges"; - - case ExecutionModeOutputLinesNV: return "OutputLinesNV"; - case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV"; - case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV"; - case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV"; - case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV"; - - case ExecutionModePixelInterlockOrderedEXT: return "PixelInterlockOrderedEXT"; - case ExecutionModePixelInterlockUnorderedEXT: return "PixelInterlockUnorderedEXT"; - case ExecutionModeSampleInterlockOrderedEXT: return "SampleInterlockOrderedEXT"; - case ExecutionModeSampleInterlockUnorderedEXT: return "SampleInterlockUnorderedEXT"; - case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT"; - case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT"; - - case ExecutionModeMaxWorkgroupSizeINTEL: return "MaxWorkgroupSizeINTEL"; - case ExecutionModeMaxWorkDimINTEL: return "MaxWorkDimINTEL"; - case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL"; - case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL"; - - case ExecutionModeRequireFullQuadsKHR: return "RequireFullQuadsKHR"; - case ExecutionModeQuadDerivativesKHR: return "QuadDerivativesKHR"; - - case ExecutionModeNonCoherentColorAttachmentReadEXT: return "NonCoherentColorAttachmentReadEXT"; - case ExecutionModeNonCoherentDepthAttachmentReadEXT: return "NonCoherentDepthAttachmentReadEXT"; - case ExecutionModeNonCoherentStencilAttachmentReadEXT: return "NonCoherentStencilAttachmentReadEXT"; - - case ExecutionModeCeiling: - default: return "Bad"; - } -} - -const char* StorageClassString(int StorageClass) -{ - switch (StorageClass) { - case 0: return "UniformConstant"; - case 1: return "Input"; - case 2: return "Uniform"; - case 3: return "Output"; - case 4: return "Workgroup"; - case 5: return "CrossWorkgroup"; - case 6: return "Private"; - case 7: return "Function"; - case 8: return "Generic"; - case 9: return "PushConstant"; - case 10: return "AtomicCounter"; - case 11: return "Image"; - case 12: return "StorageBuffer"; - - case StorageClassRayPayloadKHR: return "RayPayloadKHR"; - case StorageClassHitAttributeKHR: return "HitAttributeKHR"; - case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR"; - case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR"; - case StorageClassCallableDataKHR: return "CallableDataKHR"; - case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR"; - - case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT"; - case StorageClassTaskPayloadWorkgroupEXT: return "TaskPayloadWorkgroupEXT"; - case StorageClassHitObjectAttributeNV: return "HitObjectAttributeNV"; - case StorageClassTileImageEXT: return "TileImageEXT"; - default: return "Bad"; - } -} - -const int DecorationCeiling = 45; - -const char* DecorationString(int decoration) -{ - switch (decoration) { - case 0: return "RelaxedPrecision"; - case 1: return "SpecId"; - case 2: return "Block"; - case 3: return "BufferBlock"; - case 4: return "RowMajor"; - case 5: return "ColMajor"; - case 6: return "ArrayStride"; - case 7: return "MatrixStride"; - case 8: return "GLSLShared"; - case 9: return "GLSLPacked"; - case 10: return "CPacked"; - case 11: return "BuiltIn"; - case 12: return "Bad"; - case 13: return "NoPerspective"; - case 14: return "Flat"; - case 15: return "Patch"; - case 16: return "Centroid"; - case 17: return "Sample"; - case 18: return "Invariant"; - case 19: return "Restrict"; - case 20: return "Aliased"; - case 21: return "Volatile"; - case 22: return "Constant"; - case 23: return "Coherent"; - case 24: return "NonWritable"; - case 25: return "NonReadable"; - case 26: return "Uniform"; - case 27: return "Bad"; - case 28: return "SaturatedConversion"; - case 29: return "Stream"; - case 30: return "Location"; - case 31: return "Component"; - case 32: return "Index"; - case 33: return "Binding"; - case 34: return "DescriptorSet"; - case 35: return "Offset"; - case 36: return "XfbBuffer"; - case 37: return "XfbStride"; - case 38: return "FuncParamAttr"; - case 39: return "FP Rounding Mode"; - case 40: return "FP Fast Math Mode"; - case 41: return "Linkage Attributes"; - case 42: return "NoContraction"; - case 43: return "InputAttachmentIndex"; - case 44: return "Alignment"; - - case DecorationCeiling: - default: return "Bad"; - - case DecorationWeightTextureQCOM: return "DecorationWeightTextureQCOM"; - case DecorationBlockMatchTextureQCOM: return "DecorationBlockMatchTextureQCOM"; - case DecorationBlockMatchSamplerQCOM: return "DecorationBlockMatchSamplerQCOM"; - case DecorationExplicitInterpAMD: return "ExplicitInterpAMD"; - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; - case DecorationPerPrimitiveNV: return "PerPrimitiveNV"; - case DecorationPerViewNV: return "PerViewNV"; - case DecorationPerTaskNV: return "PerTaskNV"; - - case DecorationPerVertexKHR: return "PerVertexKHR"; - - case DecorationNonUniformEXT: return "DecorationNonUniformEXT"; - case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE"; - case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE"; - case DecorationRestrictPointerEXT: return "DecorationRestrictPointerEXT"; - case DecorationAliasedPointerEXT: return "DecorationAliasedPointerEXT"; - - case DecorationHitObjectShaderRecordBufferNV: return "DecorationHitObjectShaderRecordBufferNV"; - } -} - -const char* BuiltInString(int builtIn) -{ - switch (builtIn) { - case 0: return "Position"; - case 1: return "PointSize"; - case 2: return "Bad"; - case 3: return "ClipDistance"; - case 4: return "CullDistance"; - case 5: return "VertexId"; - case 6: return "InstanceId"; - case 7: return "PrimitiveId"; - case 8: return "InvocationId"; - case 9: return "Layer"; - case 10: return "ViewportIndex"; - case 11: return "TessLevelOuter"; - case 12: return "TessLevelInner"; - case 13: return "TessCoord"; - case 14: return "PatchVertices"; - case 15: return "FragCoord"; - case 16: return "PointCoord"; - case 17: return "FrontFacing"; - case 18: return "SampleId"; - case 19: return "SamplePosition"; - case 20: return "SampleMask"; - case 21: return "Bad"; - case 22: return "FragDepth"; - case 23: return "HelperInvocation"; - case 24: return "NumWorkgroups"; - case 25: return "WorkgroupSize"; - case 26: return "WorkgroupId"; - case 27: return "LocalInvocationId"; - case 28: return "GlobalInvocationId"; - case 29: return "LocalInvocationIndex"; - case 30: return "WorkDim"; - case 31: return "GlobalSize"; - case 32: return "EnqueuedWorkgroupSize"; - case 33: return "GlobalOffset"; - case 34: return "GlobalLinearId"; - case 35: return "Bad"; - case 36: return "SubgroupSize"; - case 37: return "SubgroupMaxSize"; - case 38: return "NumSubgroups"; - case 39: return "NumEnqueuedSubgroups"; - case 40: return "SubgroupId"; - case 41: return "SubgroupLocalInvocationId"; - case 42: return "VertexIndex"; // TBD: put next to VertexId? - case 43: return "InstanceIndex"; // TBD: put next to InstanceId? - - case 4416: return "SubgroupEqMaskKHR"; - case 4417: return "SubgroupGeMaskKHR"; - case 4418: return "SubgroupGtMaskKHR"; - case 4419: return "SubgroupLeMaskKHR"; - case 4420: return "SubgroupLtMaskKHR"; - case 4438: return "DeviceIndex"; - case 4440: return "ViewIndex"; - case 4424: return "BaseVertex"; - case 4425: return "BaseInstance"; - case 4426: return "DrawIndex"; - case 4432: return "PrimitiveShadingRateKHR"; - case 4444: return "ShadingRateKHR"; - case 5014: return "FragStencilRefEXT"; - - case 4992: return "BaryCoordNoPerspAMD"; - case 4993: return "BaryCoordNoPerspCentroidAMD"; - case 4994: return "BaryCoordNoPerspSampleAMD"; - case 4995: return "BaryCoordSmoothAMD"; - case 4996: return "BaryCoordSmoothCentroidAMD"; - case 4997: return "BaryCoordSmoothSampleAMD"; - case 4998: return "BaryCoordPullModelAMD"; - case BuiltInLaunchIdKHR: return "LaunchIdKHR"; - case BuiltInLaunchSizeKHR: return "LaunchSizeKHR"; - case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR"; - case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR"; - case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR"; - case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR"; - case BuiltInRayTminKHR: return "RayTminKHR"; - case BuiltInRayTmaxKHR: return "RayTmaxKHR"; - case BuiltInCullMaskKHR: return "CullMaskKHR"; - case BuiltInHitTriangleVertexPositionsKHR: return "HitTriangleVertexPositionsKHR"; - case BuiltInHitMicroTriangleVertexPositionsNV: return "HitMicroTriangleVertexPositionsNV"; - case BuiltInHitMicroTriangleVertexBarycentricsNV: return "HitMicroTriangleVertexBarycentricsNV"; - case BuiltInHitKindFrontFacingMicroTriangleNV: return "HitKindFrontFacingMicroTriangleNV"; - case BuiltInHitKindBackFacingMicroTriangleNV: return "HitKindBackFacingMicroTriangleNV"; - case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR"; - case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR"; - case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR"; - case BuiltInWorldToObjectKHR: return "WorldToObjectKHR"; - case BuiltInHitTNV: return "HitTNV"; - case BuiltInHitKindKHR: return "HitKindKHR"; - case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR"; - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; -// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT -// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT - case BuiltInBaryCoordKHR: return "BaryCoordKHR"; - case BuiltInBaryCoordNoPerspKHR: return "BaryCoordNoPerspKHR"; - - case BuiltInFragSizeEXT: return "FragSizeEXT"; - case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; - - case 5264: return "FullyCoveredEXT"; - - case BuiltInTaskCountNV: return "TaskCountNV"; - case BuiltInPrimitiveCountNV: return "PrimitiveCountNV"; - case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV"; - case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV"; - case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV"; - case BuiltInLayerPerViewNV: return "LayerPerViewNV"; - case BuiltInMeshViewCountNV: return "MeshViewCountNV"; - case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV"; - case BuiltInWarpsPerSMNV: return "WarpsPerSMNV"; - case BuiltInSMCountNV: return "SMCountNV"; - case BuiltInWarpIDNV: return "WarpIDNV"; - case BuiltInSMIDNV: return "SMIDNV"; - case BuiltInCurrentRayTimeNV: return "CurrentRayTimeNV"; - case BuiltInPrimitivePointIndicesEXT: return "PrimitivePointIndicesEXT"; - case BuiltInPrimitiveLineIndicesEXT: return "PrimitiveLineIndicesEXT"; - case BuiltInPrimitiveTriangleIndicesEXT: return "PrimitiveTriangleIndicesEXT"; - case BuiltInCullPrimitiveEXT: return "CullPrimitiveEXT"; - case BuiltInCoreCountARM: return "CoreCountARM"; - case BuiltInCoreIDARM: return "CoreIDARM"; - case BuiltInCoreMaxIDARM: return "CoreMaxIDARM"; - case BuiltInWarpIDARM: return "WarpIDARM"; - case BuiltInWarpMaxIDARM: return "BuiltInWarpMaxIDARM"; - - default: return "Bad"; - } -} - -const char* DimensionString(int dim) -{ - switch (dim) { - case 0: return "1D"; - case 1: return "2D"; - case 2: return "3D"; - case 3: return "Cube"; - case 4: return "Rect"; - case 5: return "Buffer"; - case 6: return "SubpassData"; - case DimTileImageDataEXT: return "TileImageDataEXT"; - - default: return "Bad"; - } -} - -const char* SamplerAddressingModeString(int mode) -{ - switch (mode) { - case 0: return "None"; - case 1: return "ClampToEdge"; - case 2: return "Clamp"; - case 3: return "Repeat"; - case 4: return "RepeatMirrored"; - - default: return "Bad"; - } -} - -const char* SamplerFilterModeString(int mode) -{ - switch (mode) { - case 0: return "Nearest"; - case 1: return "Linear"; - - default: return "Bad"; - } -} - -const char* ImageFormatString(int format) -{ - switch (format) { - case 0: return "Unknown"; - - // ES/Desktop float - case 1: return "Rgba32f"; - case 2: return "Rgba16f"; - case 3: return "R32f"; - case 4: return "Rgba8"; - case 5: return "Rgba8Snorm"; - - // Desktop float - case 6: return "Rg32f"; - case 7: return "Rg16f"; - case 8: return "R11fG11fB10f"; - case 9: return "R16f"; - case 10: return "Rgba16"; - case 11: return "Rgb10A2"; - case 12: return "Rg16"; - case 13: return "Rg8"; - case 14: return "R16"; - case 15: return "R8"; - case 16: return "Rgba16Snorm"; - case 17: return "Rg16Snorm"; - case 18: return "Rg8Snorm"; - case 19: return "R16Snorm"; - case 20: return "R8Snorm"; - - // ES/Desktop int - case 21: return "Rgba32i"; - case 22: return "Rgba16i"; - case 23: return "Rgba8i"; - case 24: return "R32i"; - - // Desktop int - case 25: return "Rg32i"; - case 26: return "Rg16i"; - case 27: return "Rg8i"; - case 28: return "R16i"; - case 29: return "R8i"; - - // ES/Desktop uint - case 30: return "Rgba32ui"; - case 31: return "Rgba16ui"; - case 32: return "Rgba8ui"; - case 33: return "R32ui"; - - // Desktop uint - case 34: return "Rgb10a2ui"; - case 35: return "Rg32ui"; - case 36: return "Rg16ui"; - case 37: return "Rg8ui"; - case 38: return "R16ui"; - case 39: return "R8ui"; - case 40: return "R64ui"; - case 41: return "R64i"; - - default: - return "Bad"; - } -} - -const char* ImageChannelOrderString(int format) -{ - switch (format) { - case 0: return "R"; - case 1: return "A"; - case 2: return "RG"; - case 3: return "RA"; - case 4: return "RGB"; - case 5: return "RGBA"; - case 6: return "BGRA"; - case 7: return "ARGB"; - case 8: return "Intensity"; - case 9: return "Luminance"; - case 10: return "Rx"; - case 11: return "RGx"; - case 12: return "RGBx"; - case 13: return "Depth"; - case 14: return "DepthStencil"; - case 15: return "sRGB"; - case 16: return "sRGBx"; - case 17: return "sRGBA"; - case 18: return "sBGRA"; - - default: - return "Bad"; - } -} - -const char* ImageChannelDataTypeString(int type) -{ - switch (type) - { - case 0: return "SnormInt8"; - case 1: return "SnormInt16"; - case 2: return "UnormInt8"; - case 3: return "UnormInt16"; - case 4: return "UnormShort565"; - case 5: return "UnormShort555"; - case 6: return "UnormInt101010"; - case 7: return "SignedInt8"; - case 8: return "SignedInt16"; - case 9: return "SignedInt32"; - case 10: return "UnsignedInt8"; - case 11: return "UnsignedInt16"; - case 12: return "UnsignedInt32"; - case 13: return "HalfFloat"; - case 14: return "Float"; - case 15: return "UnormInt24"; - case 16: return "UnormInt101010_2"; - - default: - return "Bad"; - } -} - -const int ImageOperandsCeiling = 14; - -const char* ImageOperandsString(int format) -{ - switch (format) { - case ImageOperandsBiasShift: return "Bias"; - case ImageOperandsLodShift: return "Lod"; - case ImageOperandsGradShift: return "Grad"; - case ImageOperandsConstOffsetShift: return "ConstOffset"; - case ImageOperandsOffsetShift: return "Offset"; - case ImageOperandsConstOffsetsShift: return "ConstOffsets"; - case ImageOperandsSampleShift: return "Sample"; - case ImageOperandsMinLodShift: return "MinLod"; - case ImageOperandsMakeTexelAvailableKHRShift: return "MakeTexelAvailableKHR"; - case ImageOperandsMakeTexelVisibleKHRShift: return "MakeTexelVisibleKHR"; - case ImageOperandsNonPrivateTexelKHRShift: return "NonPrivateTexelKHR"; - case ImageOperandsVolatileTexelKHRShift: return "VolatileTexelKHR"; - case ImageOperandsSignExtendShift: return "SignExtend"; - case ImageOperandsZeroExtendShift: return "ZeroExtend"; - - case ImageOperandsCeiling: - default: - return "Bad"; - } -} - -const char* FPFastMathString(int mode) -{ - switch (mode) { - case 0: return "NotNaN"; - case 1: return "NotInf"; - case 2: return "NSZ"; - case 3: return "AllowRecip"; - case 4: return "Fast"; - - default: return "Bad"; - } -} - -const char* FPRoundingModeString(int mode) -{ - switch (mode) { - case 0: return "RTE"; - case 1: return "RTZ"; - case 2: return "RTP"; - case 3: return "RTN"; - - default: return "Bad"; - } -} - -const char* LinkageTypeString(int type) -{ - switch (type) { - case 0: return "Export"; - case 1: return "Import"; - - default: return "Bad"; - } -} - -const char* FuncParamAttrString(int attr) -{ - switch (attr) { - case 0: return "Zext"; - case 1: return "Sext"; - case 2: return "ByVal"; - case 3: return "Sret"; - case 4: return "NoAlias"; - case 5: return "NoCapture"; - case 6: return "NoWrite"; - case 7: return "NoReadWrite"; - - default: return "Bad"; - } -} - -const char* AccessQualifierString(int attr) -{ - switch (attr) { - case 0: return "ReadOnly"; - case 1: return "WriteOnly"; - case 2: return "ReadWrite"; - - default: return "Bad"; - } -} - -const int SelectControlCeiling = 2; - -const char* SelectControlString(int cont) -{ - switch (cont) { - case 0: return "Flatten"; - case 1: return "DontFlatten"; - - case SelectControlCeiling: - default: return "Bad"; - } -} - -const int LoopControlCeiling = LoopControlPartialCountShift + 1; - -const char* LoopControlString(int cont) -{ - switch (cont) { - case LoopControlUnrollShift: return "Unroll"; - case LoopControlDontUnrollShift: return "DontUnroll"; - case LoopControlDependencyInfiniteShift: return "DependencyInfinite"; - case LoopControlDependencyLengthShift: return "DependencyLength"; - case LoopControlMinIterationsShift: return "MinIterations"; - case LoopControlMaxIterationsShift: return "MaxIterations"; - case LoopControlIterationMultipleShift: return "IterationMultiple"; - case LoopControlPeelCountShift: return "PeelCount"; - case LoopControlPartialCountShift: return "PartialCount"; - - case LoopControlCeiling: - default: return "Bad"; - } -} - -const int FunctionControlCeiling = 4; - -const char* FunctionControlString(int cont) -{ - switch (cont) { - case 0: return "Inline"; - case 1: return "DontInline"; - case 2: return "Pure"; - case 3: return "Const"; - - case FunctionControlCeiling: - default: return "Bad"; - } -} - -const char* MemorySemanticsString(int mem) -{ - // Note: No bits set (None) means "Relaxed" - switch (mem) { - case 0: return "Bad"; // Note: this is a placeholder for 'Consume' - case 1: return "Acquire"; - case 2: return "Release"; - case 3: return "AcquireRelease"; - case 4: return "SequentiallyConsistent"; - case 5: return "Bad"; // Note: reserved for future expansion - case 6: return "UniformMemory"; - case 7: return "SubgroupMemory"; - case 8: return "WorkgroupMemory"; - case 9: return "CrossWorkgroupMemory"; - case 10: return "AtomicCounterMemory"; - case 11: return "ImageMemory"; - - default: return "Bad"; - } -} - -const int MemoryAccessCeiling = 6; - -const char* MemoryAccessString(int mem) -{ - switch (mem) { - case MemoryAccessVolatileShift: return "Volatile"; - case MemoryAccessAlignedShift: return "Aligned"; - case MemoryAccessNontemporalShift: return "Nontemporal"; - case MemoryAccessMakePointerAvailableKHRShift: return "MakePointerAvailableKHR"; - case MemoryAccessMakePointerVisibleKHRShift: return "MakePointerVisibleKHR"; - case MemoryAccessNonPrivatePointerKHRShift: return "NonPrivatePointerKHR"; - - default: return "Bad"; - } -} - -const int CooperativeMatrixOperandsCeiling = 6; - -const char* CooperativeMatrixOperandsString(int op) -{ - switch (op) { - case CooperativeMatrixOperandsMatrixASignedComponentsKHRShift: return "ASignedComponentsKHR"; - case CooperativeMatrixOperandsMatrixBSignedComponentsKHRShift: return "BSignedComponentsKHR"; - case CooperativeMatrixOperandsMatrixCSignedComponentsKHRShift: return "CSignedComponentsKHR"; - case CooperativeMatrixOperandsMatrixResultSignedComponentsKHRShift: return "ResultSignedComponentsKHR"; - case CooperativeMatrixOperandsSaturatingAccumulationKHRShift: return "SaturatingAccumulationKHR"; - - default: return "Bad"; - } -} - -const int TensorAddressingOperandsCeiling = 3; - -const char* TensorAddressingOperandsString(int op) -{ - switch (op) { - case TensorAddressingOperandsTensorViewShift: return "TensorView"; - case TensorAddressingOperandsDecodeFuncShift: return "DecodeFunc"; - - default: return "Bad"; - } -} - -const char* ScopeString(int mem) -{ - switch (mem) { - case 0: return "CrossDevice"; - case 1: return "Device"; - case 2: return "Workgroup"; - case 3: return "Subgroup"; - case 4: return "Invocation"; - - default: return "Bad"; - } -} - -const char* GroupOperationString(int gop) -{ - - switch (gop) - { - case GroupOperationReduce: return "Reduce"; - case GroupOperationInclusiveScan: return "InclusiveScan"; - case GroupOperationExclusiveScan: return "ExclusiveScan"; - case GroupOperationClusteredReduce: return "ClusteredReduce"; - case GroupOperationPartitionedReduceNV: return "PartitionedReduceNV"; - case GroupOperationPartitionedInclusiveScanNV: return "PartitionedInclusiveScanNV"; - case GroupOperationPartitionedExclusiveScanNV: return "PartitionedExclusiveScanNV"; - - default: return "Bad"; - } -} - -const char* KernelEnqueueFlagsString(int flag) -{ - switch (flag) - { - case 0: return "NoWait"; - case 1: return "WaitKernel"; - case 2: return "WaitWorkGroup"; - - default: return "Bad"; - } -} - -const char* KernelProfilingInfoString(int info) -{ - switch (info) - { - case 0: return "CmdExecTime"; - - default: return "Bad"; - } -} - -const char* CapabilityString(int info) -{ - switch (info) - { - case 0: return "Matrix"; - case 1: return "Shader"; - case 2: return "Geometry"; - case 3: return "Tessellation"; - case 4: return "Addresses"; - case 5: return "Linkage"; - case 6: return "Kernel"; - case 7: return "Vector16"; - case 8: return "Float16Buffer"; - case 9: return "Float16"; - case 10: return "Float64"; - case 11: return "Int64"; - case 12: return "Int64Atomics"; - case 13: return "ImageBasic"; - case 14: return "ImageReadWrite"; - case 15: return "ImageMipmap"; - case 16: return "Bad"; - case 17: return "Pipes"; - case 18: return "Groups"; - case 19: return "DeviceEnqueue"; - case 20: return "LiteralSampler"; - case 21: return "AtomicStorage"; - case 22: return "Int16"; - case 23: return "TessellationPointSize"; - case 24: return "GeometryPointSize"; - case 25: return "ImageGatherExtended"; - case 26: return "Bad"; - case 27: return "StorageImageMultisample"; - case 28: return "UniformBufferArrayDynamicIndexing"; - case 29: return "SampledImageArrayDynamicIndexing"; - case 30: return "StorageBufferArrayDynamicIndexing"; - case 31: return "StorageImageArrayDynamicIndexing"; - case 32: return "ClipDistance"; - case 33: return "CullDistance"; - case 34: return "ImageCubeArray"; - case 35: return "SampleRateShading"; - case 36: return "ImageRect"; - case 37: return "SampledRect"; - case 38: return "GenericPointer"; - case 39: return "Int8"; - case 40: return "InputAttachment"; - case 41: return "SparseResidency"; - case 42: return "MinLod"; - case 43: return "Sampled1D"; - case 44: return "Image1D"; - case 45: return "SampledCubeArray"; - case 46: return "SampledBuffer"; - case 47: return "ImageBuffer"; - case 48: return "ImageMSArray"; - case 49: return "StorageImageExtendedFormats"; - case 50: return "ImageQuery"; - case 51: return "DerivativeControl"; - case 52: return "InterpolationFunction"; - case 53: return "TransformFeedback"; - case 54: return "GeometryStreams"; - case 55: return "StorageImageReadWithoutFormat"; - case 56: return "StorageImageWriteWithoutFormat"; - case 57: return "MultiViewport"; - case 61: return "GroupNonUniform"; - case 62: return "GroupNonUniformVote"; - case 63: return "GroupNonUniformArithmetic"; - case 64: return "GroupNonUniformBallot"; - case 65: return "GroupNonUniformShuffle"; - case 66: return "GroupNonUniformShuffleRelative"; - case 67: return "GroupNonUniformClustered"; - case 68: return "GroupNonUniformQuad"; - - case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR"; - case CapabilityDrawParameters: return "DrawParameters"; - case CapabilitySubgroupVoteKHR: return "SubgroupVoteKHR"; - case CapabilityGroupNonUniformRotateKHR: return "CapabilityGroupNonUniformRotateKHR"; - - case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16"; - case CapabilityStorageUniform16: return "StorageUniform16"; - case CapabilityStoragePushConstant16: return "StoragePushConstant16"; - case CapabilityStorageInputOutput16: return "StorageInputOutput16"; - - case CapabilityStorageBuffer8BitAccess: return "StorageBuffer8BitAccess"; - case CapabilityUniformAndStorageBuffer8BitAccess: return "UniformAndStorageBuffer8BitAccess"; - case CapabilityStoragePushConstant8: return "StoragePushConstant8"; - - case CapabilityDeviceGroup: return "DeviceGroup"; - case CapabilityMultiView: return "MultiView"; - - case CapabilityDenormPreserve: return "DenormPreserve"; - case CapabilityDenormFlushToZero: return "DenormFlushToZero"; - case CapabilitySignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; - case CapabilityRoundingModeRTE: return "RoundingModeRTE"; - case CapabilityRoundingModeRTZ: return "RoundingModeRTZ"; - - case CapabilityStencilExportEXT: return "StencilExportEXT"; - - case CapabilityFloat16ImageAMD: return "Float16ImageAMD"; - case CapabilityImageGatherBiasLodAMD: return "ImageGatherBiasLodAMD"; - case CapabilityFragmentMaskAMD: return "FragmentMaskAMD"; - case CapabilityImageReadWriteLodAMD: return "ImageReadWriteLodAMD"; - - case CapabilityAtomicStorageOps: return "AtomicStorageOps"; - - case CapabilitySampleMaskPostDepthCoverage: return "SampleMaskPostDepthCoverage"; - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case CapabilityShaderViewportIndexLayerNV: return "ShaderViewportIndexLayerNV"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; - case CapabilityRayTracingNV: return "RayTracingNV"; - case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV"; - case CapabilityRayTracingKHR: return "RayTracingKHR"; - case CapabilityRayCullMaskKHR: return "RayCullMaskKHR"; - case CapabilityRayQueryKHR: return "RayQueryKHR"; - case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR"; - case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR"; - case CapabilityRayTracingPositionFetchKHR: return "RayTracingPositionFetchKHR"; - case CapabilityDisplacementMicromapNV: return "DisplacementMicromapNV"; - case CapabilityRayTracingDisplacementMicromapNV: return "CapabilityRayTracingDisplacementMicromapNV"; - case CapabilityRayQueryPositionFetchKHR: return "RayQueryPositionFetchKHR"; - case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV"; - case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; - case CapabilityFragmentBarycentricKHR: return "FragmentBarycentricKHR"; - case CapabilityMeshShadingNV: return "MeshShadingNV"; - case CapabilityImageFootprintNV: return "ImageFootprintNV"; - case CapabilityMeshShadingEXT: return "MeshShadingEXT"; -// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by FragmentDensityEXT - case CapabilitySampleMaskOverrideCoverageNV: return "SampleMaskOverrideCoverageNV"; - case CapabilityFragmentDensityEXT: return "FragmentDensityEXT"; - - case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT"; - - case CapabilityShaderNonUniformEXT: return "ShaderNonUniformEXT"; - case CapabilityRuntimeDescriptorArrayEXT: return "RuntimeDescriptorArrayEXT"; - case CapabilityInputAttachmentArrayDynamicIndexingEXT: return "InputAttachmentArrayDynamicIndexingEXT"; - case CapabilityUniformTexelBufferArrayDynamicIndexingEXT: return "UniformTexelBufferArrayDynamicIndexingEXT"; - case CapabilityStorageTexelBufferArrayDynamicIndexingEXT: return "StorageTexelBufferArrayDynamicIndexingEXT"; - case CapabilityUniformBufferArrayNonUniformIndexingEXT: return "UniformBufferArrayNonUniformIndexingEXT"; - case CapabilitySampledImageArrayNonUniformIndexingEXT: return "SampledImageArrayNonUniformIndexingEXT"; - case CapabilityStorageBufferArrayNonUniformIndexingEXT: return "StorageBufferArrayNonUniformIndexingEXT"; - case CapabilityStorageImageArrayNonUniformIndexingEXT: return "StorageImageArrayNonUniformIndexingEXT"; - case CapabilityInputAttachmentArrayNonUniformIndexingEXT: return "InputAttachmentArrayNonUniformIndexingEXT"; - case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "UniformTexelBufferArrayNonUniformIndexingEXT"; - case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "StorageTexelBufferArrayNonUniformIndexingEXT"; - - case CapabilityVulkanMemoryModelKHR: return "VulkanMemoryModelKHR"; - case CapabilityVulkanMemoryModelDeviceScopeKHR: return "VulkanMemoryModelDeviceScopeKHR"; - - case CapabilityPhysicalStorageBufferAddressesEXT: return "PhysicalStorageBufferAddressesEXT"; - - case CapabilityVariablePointers: return "VariablePointers"; - - case CapabilityCooperativeMatrixNV: return "CooperativeMatrixNV"; - case CapabilityCooperativeMatrixKHR: return "CooperativeMatrixKHR"; - case CapabilityCooperativeMatrixReductionsNV: return "CooperativeMatrixReductionsNV"; - case CapabilityCooperativeMatrixConversionsNV: return "CooperativeMatrixConversionsNV"; - case CapabilityCooperativeMatrixPerElementOperationsNV: return "CooperativeMatrixPerElementOperationsNV"; - case CapabilityCooperativeMatrixTensorAddressingNV: return "CooperativeMatrixTensorAddressingNV"; - case CapabilityCooperativeMatrixBlockLoadsNV: return "CooperativeMatrixBlockLoadsNV"; - case CapabilityTensorAddressingNV: return "TensorAddressingNV"; - - case CapabilityShaderSMBuiltinsNV: return "ShaderSMBuiltinsNV"; - - case CapabilityFragmentShaderSampleInterlockEXT: return "CapabilityFragmentShaderSampleInterlockEXT"; - case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT"; - case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT"; - - case CapabilityTileImageColorReadAccessEXT: return "TileImageColorReadAccessEXT"; - case CapabilityTileImageDepthReadAccessEXT: return "TileImageDepthReadAccessEXT"; - case CapabilityTileImageStencilReadAccessEXT: return "TileImageStencilReadAccessEXT"; - - case CapabilityCooperativeMatrixLayoutsARM: return "CooperativeMatrixLayoutsARM"; - - case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR"; - - case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT"; - case CapabilityAtomicFloat16VectorNV: return "AtomicFloat16VectorNV"; - case CapabilityShaderClockKHR: return "ShaderClockKHR"; - case CapabilityQuadControlKHR: return "QuadControlKHR"; - case CapabilityInt64ImageEXT: return "Int64ImageEXT"; - - case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL"; - - case CapabilityExpectAssumeKHR: return "ExpectAssumeKHR"; - - case CapabilityAtomicFloat16AddEXT: return "AtomicFloat16AddEXT"; - case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT"; - case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT"; - case CapabilityAtomicFloat16MinMaxEXT: return "AtomicFloat16MinMaxEXT"; - case CapabilityAtomicFloat32MinMaxEXT: return "AtomicFloat32MinMaxEXT"; - case CapabilityAtomicFloat64MinMaxEXT: return "AtomicFloat64MinMaxEXT"; - - case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "CapabilityWorkgroupMemoryExplicitLayoutKHR"; - case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR"; - case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR"; - case CapabilityCoreBuiltinsARM: return "CoreBuiltinsARM"; - - case CapabilityShaderInvocationReorderNV: return "ShaderInvocationReorderNV"; - - case CapabilityTextureSampleWeightedQCOM: return "TextureSampleWeightedQCOM"; - case CapabilityTextureBoxFilterQCOM: return "TextureBoxFilterQCOM"; - case CapabilityTextureBlockMatchQCOM: return "TextureBlockMatchQCOM"; - case CapabilityTextureBlockMatch2QCOM: return "TextureBlockMatch2QCOM"; - - case CapabilityReplicatedCompositesEXT: return "CapabilityReplicatedCompositesEXT"; - - default: return "Bad"; - } -} - -const char* OpcodeString(int op) -{ - switch (op) { - case 0: return "OpNop"; - case 1: return "OpUndef"; - case 2: return "OpSourceContinued"; - case 3: return "OpSource"; - case 4: return "OpSourceExtension"; - case 5: return "OpName"; - case 6: return "OpMemberName"; - case 7: return "OpString"; - case 8: return "OpLine"; - case 9: return "Bad"; - case 10: return "OpExtension"; - case 11: return "OpExtInstImport"; - case 12: return "OpExtInst"; - case 13: return "Bad"; - case 14: return "OpMemoryModel"; - case 15: return "OpEntryPoint"; - case 16: return "OpExecutionMode"; - case 17: return "OpCapability"; - case 18: return "Bad"; - case 19: return "OpTypeVoid"; - case 20: return "OpTypeBool"; - case 21: return "OpTypeInt"; - case 22: return "OpTypeFloat"; - case 23: return "OpTypeVector"; - case 24: return "OpTypeMatrix"; - case 25: return "OpTypeImage"; - case 26: return "OpTypeSampler"; - case 27: return "OpTypeSampledImage"; - case 28: return "OpTypeArray"; - case 29: return "OpTypeRuntimeArray"; - case 30: return "OpTypeStruct"; - case 31: return "OpTypeOpaque"; - case 32: return "OpTypePointer"; - case 33: return "OpTypeFunction"; - case 34: return "OpTypeEvent"; - case 35: return "OpTypeDeviceEvent"; - case 36: return "OpTypeReserveId"; - case 37: return "OpTypeQueue"; - case 38: return "OpTypePipe"; - case 39: return "OpTypeForwardPointer"; - case 40: return "Bad"; - case 41: return "OpConstantTrue"; - case 42: return "OpConstantFalse"; - case 43: return "OpConstant"; - case 44: return "OpConstantComposite"; - case 45: return "OpConstantSampler"; - case 46: return "OpConstantNull"; - case 47: return "Bad"; - case 48: return "OpSpecConstantTrue"; - case 49: return "OpSpecConstantFalse"; - case 50: return "OpSpecConstant"; - case 51: return "OpSpecConstantComposite"; - case 52: return "OpSpecConstantOp"; - case 53: return "Bad"; - case 54: return "OpFunction"; - case 55: return "OpFunctionParameter"; - case 56: return "OpFunctionEnd"; - case 57: return "OpFunctionCall"; - case 58: return "Bad"; - case 59: return "OpVariable"; - case 60: return "OpImageTexelPointer"; - case 61: return "OpLoad"; - case 62: return "OpStore"; - case 63: return "OpCopyMemory"; - case 64: return "OpCopyMemorySized"; - case 65: return "OpAccessChain"; - case 66: return "OpInBoundsAccessChain"; - case 67: return "OpPtrAccessChain"; - case 68: return "OpArrayLength"; - case 69: return "OpGenericPtrMemSemantics"; - case 70: return "OpInBoundsPtrAccessChain"; - case 71: return "OpDecorate"; - case 72: return "OpMemberDecorate"; - case 73: return "OpDecorationGroup"; - case 74: return "OpGroupDecorate"; - case 75: return "OpGroupMemberDecorate"; - case 76: return "Bad"; - case 77: return "OpVectorExtractDynamic"; - case 78: return "OpVectorInsertDynamic"; - case 79: return "OpVectorShuffle"; - case 80: return "OpCompositeConstruct"; - case 81: return "OpCompositeExtract"; - case 82: return "OpCompositeInsert"; - case 83: return "OpCopyObject"; - case 84: return "OpTranspose"; - case OpCopyLogical: return "OpCopyLogical"; - case 85: return "Bad"; - case 86: return "OpSampledImage"; - case 87: return "OpImageSampleImplicitLod"; - case 88: return "OpImageSampleExplicitLod"; - case 89: return "OpImageSampleDrefImplicitLod"; - case 90: return "OpImageSampleDrefExplicitLod"; - case 91: return "OpImageSampleProjImplicitLod"; - case 92: return "OpImageSampleProjExplicitLod"; - case 93: return "OpImageSampleProjDrefImplicitLod"; - case 94: return "OpImageSampleProjDrefExplicitLod"; - case 95: return "OpImageFetch"; - case 96: return "OpImageGather"; - case 97: return "OpImageDrefGather"; - case 98: return "OpImageRead"; - case 99: return "OpImageWrite"; - case 100: return "OpImage"; - case 101: return "OpImageQueryFormat"; - case 102: return "OpImageQueryOrder"; - case 103: return "OpImageQuerySizeLod"; - case 104: return "OpImageQuerySize"; - case 105: return "OpImageQueryLod"; - case 106: return "OpImageQueryLevels"; - case 107: return "OpImageQuerySamples"; - case 108: return "Bad"; - case 109: return "OpConvertFToU"; - case 110: return "OpConvertFToS"; - case 111: return "OpConvertSToF"; - case 112: return "OpConvertUToF"; - case 113: return "OpUConvert"; - case 114: return "OpSConvert"; - case 115: return "OpFConvert"; - case 116: return "OpQuantizeToF16"; - case 117: return "OpConvertPtrToU"; - case 118: return "OpSatConvertSToU"; - case 119: return "OpSatConvertUToS"; - case 120: return "OpConvertUToPtr"; - case 121: return "OpPtrCastToGeneric"; - case 122: return "OpGenericCastToPtr"; - case 123: return "OpGenericCastToPtrExplicit"; - case 124: return "OpBitcast"; - case 125: return "Bad"; - case 126: return "OpSNegate"; - case 127: return "OpFNegate"; - case 128: return "OpIAdd"; - case 129: return "OpFAdd"; - case 130: return "OpISub"; - case 131: return "OpFSub"; - case 132: return "OpIMul"; - case 133: return "OpFMul"; - case 134: return "OpUDiv"; - case 135: return "OpSDiv"; - case 136: return "OpFDiv"; - case 137: return "OpUMod"; - case 138: return "OpSRem"; - case 139: return "OpSMod"; - case 140: return "OpFRem"; - case 141: return "OpFMod"; - case 142: return "OpVectorTimesScalar"; - case 143: return "OpMatrixTimesScalar"; - case 144: return "OpVectorTimesMatrix"; - case 145: return "OpMatrixTimesVector"; - case 146: return "OpMatrixTimesMatrix"; - case 147: return "OpOuterProduct"; - case 148: return "OpDot"; - case 149: return "OpIAddCarry"; - case 150: return "OpISubBorrow"; - case 151: return "OpUMulExtended"; - case 152: return "OpSMulExtended"; - case 153: return "Bad"; - case 154: return "OpAny"; - case 155: return "OpAll"; - case 156: return "OpIsNan"; - case 157: return "OpIsInf"; - case 158: return "OpIsFinite"; - case 159: return "OpIsNormal"; - case 160: return "OpSignBitSet"; - case 161: return "OpLessOrGreater"; - case 162: return "OpOrdered"; - case 163: return "OpUnordered"; - case 164: return "OpLogicalEqual"; - case 165: return "OpLogicalNotEqual"; - case 166: return "OpLogicalOr"; - case 167: return "OpLogicalAnd"; - case 168: return "OpLogicalNot"; - case 169: return "OpSelect"; - case 170: return "OpIEqual"; - case 171: return "OpINotEqual"; - case 172: return "OpUGreaterThan"; - case 173: return "OpSGreaterThan"; - case 174: return "OpUGreaterThanEqual"; - case 175: return "OpSGreaterThanEqual"; - case 176: return "OpULessThan"; - case 177: return "OpSLessThan"; - case 178: return "OpULessThanEqual"; - case 179: return "OpSLessThanEqual"; - case 180: return "OpFOrdEqual"; - case 181: return "OpFUnordEqual"; - case 182: return "OpFOrdNotEqual"; - case 183: return "OpFUnordNotEqual"; - case 184: return "OpFOrdLessThan"; - case 185: return "OpFUnordLessThan"; - case 186: return "OpFOrdGreaterThan"; - case 187: return "OpFUnordGreaterThan"; - case 188: return "OpFOrdLessThanEqual"; - case 189: return "OpFUnordLessThanEqual"; - case 190: return "OpFOrdGreaterThanEqual"; - case 191: return "OpFUnordGreaterThanEqual"; - case 192: return "Bad"; - case 193: return "Bad"; - case 194: return "OpShiftRightLogical"; - case 195: return "OpShiftRightArithmetic"; - case 196: return "OpShiftLeftLogical"; - case 197: return "OpBitwiseOr"; - case 198: return "OpBitwiseXor"; - case 199: return "OpBitwiseAnd"; - case 200: return "OpNot"; - case 201: return "OpBitFieldInsert"; - case 202: return "OpBitFieldSExtract"; - case 203: return "OpBitFieldUExtract"; - case 204: return "OpBitReverse"; - case 205: return "OpBitCount"; - case 206: return "Bad"; - case 207: return "OpDPdx"; - case 208: return "OpDPdy"; - case 209: return "OpFwidth"; - case 210: return "OpDPdxFine"; - case 211: return "OpDPdyFine"; - case 212: return "OpFwidthFine"; - case 213: return "OpDPdxCoarse"; - case 214: return "OpDPdyCoarse"; - case 215: return "OpFwidthCoarse"; - case 216: return "Bad"; - case 217: return "Bad"; - case 218: return "OpEmitVertex"; - case 219: return "OpEndPrimitive"; - case 220: return "OpEmitStreamVertex"; - case 221: return "OpEndStreamPrimitive"; - case 222: return "Bad"; - case 223: return "Bad"; - case 224: return "OpControlBarrier"; - case 225: return "OpMemoryBarrier"; - case 226: return "Bad"; - case 227: return "OpAtomicLoad"; - case 228: return "OpAtomicStore"; - case 229: return "OpAtomicExchange"; - case 230: return "OpAtomicCompareExchange"; - case 231: return "OpAtomicCompareExchangeWeak"; - case 232: return "OpAtomicIIncrement"; - case 233: return "OpAtomicIDecrement"; - case 234: return "OpAtomicIAdd"; - case 235: return "OpAtomicISub"; - case 236: return "OpAtomicSMin"; - case 237: return "OpAtomicUMin"; - case 238: return "OpAtomicSMax"; - case 239: return "OpAtomicUMax"; - case 240: return "OpAtomicAnd"; - case 241: return "OpAtomicOr"; - case 242: return "OpAtomicXor"; - case 243: return "Bad"; - case 244: return "Bad"; - case 245: return "OpPhi"; - case 246: return "OpLoopMerge"; - case 247: return "OpSelectionMerge"; - case 248: return "OpLabel"; - case 249: return "OpBranch"; - case 250: return "OpBranchConditional"; - case 251: return "OpSwitch"; - case 252: return "OpKill"; - case 253: return "OpReturn"; - case 254: return "OpReturnValue"; - case 255: return "OpUnreachable"; - case 256: return "OpLifetimeStart"; - case 257: return "OpLifetimeStop"; - case 258: return "Bad"; - case 259: return "OpGroupAsyncCopy"; - case 260: return "OpGroupWaitEvents"; - case 261: return "OpGroupAll"; - case 262: return "OpGroupAny"; - case 263: return "OpGroupBroadcast"; - case 264: return "OpGroupIAdd"; - case 265: return "OpGroupFAdd"; - case 266: return "OpGroupFMin"; - case 267: return "OpGroupUMin"; - case 268: return "OpGroupSMin"; - case 269: return "OpGroupFMax"; - case 270: return "OpGroupUMax"; - case 271: return "OpGroupSMax"; - case 272: return "Bad"; - case 273: return "Bad"; - case 274: return "OpReadPipe"; - case 275: return "OpWritePipe"; - case 276: return "OpReservedReadPipe"; - case 277: return "OpReservedWritePipe"; - case 278: return "OpReserveReadPipePackets"; - case 279: return "OpReserveWritePipePackets"; - case 280: return "OpCommitReadPipe"; - case 281: return "OpCommitWritePipe"; - case 282: return "OpIsValidReserveId"; - case 283: return "OpGetNumPipePackets"; - case 284: return "OpGetMaxPipePackets"; - case 285: return "OpGroupReserveReadPipePackets"; - case 286: return "OpGroupReserveWritePipePackets"; - case 287: return "OpGroupCommitReadPipe"; - case 288: return "OpGroupCommitWritePipe"; - case 289: return "Bad"; - case 290: return "Bad"; - case 291: return "OpEnqueueMarker"; - case 292: return "OpEnqueueKernel"; - case 293: return "OpGetKernelNDrangeSubGroupCount"; - case 294: return "OpGetKernelNDrangeMaxSubGroupSize"; - case 295: return "OpGetKernelWorkGroupSize"; - case 296: return "OpGetKernelPreferredWorkGroupSizeMultiple"; - case 297: return "OpRetainEvent"; - case 298: return "OpReleaseEvent"; - case 299: return "OpCreateUserEvent"; - case 300: return "OpIsValidEvent"; - case 301: return "OpSetUserEventStatus"; - case 302: return "OpCaptureEventProfilingInfo"; - case 303: return "OpGetDefaultQueue"; - case 304: return "OpBuildNDRange"; - case 305: return "OpImageSparseSampleImplicitLod"; - case 306: return "OpImageSparseSampleExplicitLod"; - case 307: return "OpImageSparseSampleDrefImplicitLod"; - case 308: return "OpImageSparseSampleDrefExplicitLod"; - case 309: return "OpImageSparseSampleProjImplicitLod"; - case 310: return "OpImageSparseSampleProjExplicitLod"; - case 311: return "OpImageSparseSampleProjDrefImplicitLod"; - case 312: return "OpImageSparseSampleProjDrefExplicitLod"; - case 313: return "OpImageSparseFetch"; - case 314: return "OpImageSparseGather"; - case 315: return "OpImageSparseDrefGather"; - case 316: return "OpImageSparseTexelsResident"; - case 317: return "OpNoLine"; - case 318: return "OpAtomicFlagTestAndSet"; - case 319: return "OpAtomicFlagClear"; - case 320: return "OpImageSparseRead"; - - case OpModuleProcessed: return "OpModuleProcessed"; - case OpExecutionModeId: return "OpExecutionModeId"; - case OpDecorateId: return "OpDecorateId"; - - case 333: return "OpGroupNonUniformElect"; - case 334: return "OpGroupNonUniformAll"; - case 335: return "OpGroupNonUniformAny"; - case 336: return "OpGroupNonUniformAllEqual"; - case 337: return "OpGroupNonUniformBroadcast"; - case 338: return "OpGroupNonUniformBroadcastFirst"; - case 339: return "OpGroupNonUniformBallot"; - case 340: return "OpGroupNonUniformInverseBallot"; - case 341: return "OpGroupNonUniformBallotBitExtract"; - case 342: return "OpGroupNonUniformBallotBitCount"; - case 343: return "OpGroupNonUniformBallotFindLSB"; - case 344: return "OpGroupNonUniformBallotFindMSB"; - case 345: return "OpGroupNonUniformShuffle"; - case 346: return "OpGroupNonUniformShuffleXor"; - case 347: return "OpGroupNonUniformShuffleUp"; - case 348: return "OpGroupNonUniformShuffleDown"; - case 349: return "OpGroupNonUniformIAdd"; - case 350: return "OpGroupNonUniformFAdd"; - case 351: return "OpGroupNonUniformIMul"; - case 352: return "OpGroupNonUniformFMul"; - case 353: return "OpGroupNonUniformSMin"; - case 354: return "OpGroupNonUniformUMin"; - case 355: return "OpGroupNonUniformFMin"; - case 356: return "OpGroupNonUniformSMax"; - case 357: return "OpGroupNonUniformUMax"; - case 358: return "OpGroupNonUniformFMax"; - case 359: return "OpGroupNonUniformBitwiseAnd"; - case 360: return "OpGroupNonUniformBitwiseOr"; - case 361: return "OpGroupNonUniformBitwiseXor"; - case 362: return "OpGroupNonUniformLogicalAnd"; - case 363: return "OpGroupNonUniformLogicalOr"; - case 364: return "OpGroupNonUniformLogicalXor"; - case 365: return "OpGroupNonUniformQuadBroadcast"; - case 366: return "OpGroupNonUniformQuadSwap"; - - case OpTerminateInvocation: return "OpTerminateInvocation"; - - case 4421: return "OpSubgroupBallotKHR"; - case 4422: return "OpSubgroupFirstInvocationKHR"; - case 4428: return "OpSubgroupAllKHR"; - case 4429: return "OpSubgroupAnyKHR"; - case 4430: return "OpSubgroupAllEqualKHR"; - case 4432: return "OpSubgroupReadInvocationKHR"; - case 4433: return "OpExtInstWithForwardRefsKHR"; - - case OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR"; - case OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR"; - - case OpAtomicFAddEXT: return "OpAtomicFAddEXT"; - case OpAtomicFMinEXT: return "OpAtomicFMinEXT"; - case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT"; - - case OpAssumeTrueKHR: return "OpAssumeTrueKHR"; - case OpExpectKHR: return "OpExpectKHR"; - - case 5000: return "OpGroupIAddNonUniformAMD"; - case 5001: return "OpGroupFAddNonUniformAMD"; - case 5002: return "OpGroupFMinNonUniformAMD"; - case 5003: return "OpGroupUMinNonUniformAMD"; - case 5004: return "OpGroupSMinNonUniformAMD"; - case 5005: return "OpGroupFMaxNonUniformAMD"; - case 5006: return "OpGroupUMaxNonUniformAMD"; - case 5007: return "OpGroupSMaxNonUniformAMD"; - - case 5011: return "OpFragmentMaskFetchAMD"; - case 5012: return "OpFragmentFetchAMD"; - - case OpReadClockKHR: return "OpReadClockKHR"; - - case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE"; - case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE"; - - case OpReportIntersectionKHR: return "OpReportIntersectionKHR"; - case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV"; - case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR"; - case OpTerminateRayNV: return "OpTerminateRayNV"; - case OpTerminateRayKHR: return "OpTerminateRayKHR"; - case OpTraceNV: return "OpTraceNV"; - case OpTraceRayMotionNV: return "OpTraceRayMotionNV"; - case OpTraceRayKHR: return "OpTraceRayKHR"; - case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR"; - case OpExecuteCallableNV: return "OpExecuteCallableNV"; - case OpExecuteCallableKHR: return "OpExecuteCallableKHR"; - case OpConvertUToAccelerationStructureKHR: return "OpConvertUToAccelerationStructureKHR"; - - case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV"; - case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV"; - case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV"; - case OpEmitMeshTasksEXT: return "OpEmitMeshTasksEXT"; - case OpSetMeshOutputsEXT: return "OpSetMeshOutputsEXT"; - - case OpGroupNonUniformRotateKHR: return "OpGroupNonUniformRotateKHR"; - - case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR"; - case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR"; - case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR"; - case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR"; - case OpRayQueryConfirmIntersectionKHR: return "OpRayQueryConfirmIntersectionKHR"; - case OpRayQueryProceedKHR: return "OpRayQueryProceedKHR"; - case OpRayQueryGetIntersectionTypeKHR: return "OpRayQueryGetIntersectionTypeKHR"; - case OpRayQueryGetRayTMinKHR: return "OpRayQueryGetRayTMinKHR"; - case OpRayQueryGetRayFlagsKHR: return "OpRayQueryGetRayFlagsKHR"; - case OpRayQueryGetIntersectionTKHR: return "OpRayQueryGetIntersectionTKHR"; - case OpRayQueryGetIntersectionInstanceCustomIndexKHR: return "OpRayQueryGetIntersectionInstanceCustomIndexKHR"; - case OpRayQueryGetIntersectionInstanceIdKHR: return "OpRayQueryGetIntersectionInstanceIdKHR"; - case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR"; - case OpRayQueryGetIntersectionGeometryIndexKHR: return "OpRayQueryGetIntersectionGeometryIndexKHR"; - case OpRayQueryGetIntersectionPrimitiveIndexKHR: return "OpRayQueryGetIntersectionPrimitiveIndexKHR"; - case OpRayQueryGetIntersectionBarycentricsKHR: return "OpRayQueryGetIntersectionBarycentricsKHR"; - case OpRayQueryGetIntersectionFrontFaceKHR: return "OpRayQueryGetIntersectionFrontFaceKHR"; - case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR"; - case OpRayQueryGetIntersectionObjectRayDirectionKHR: return "OpRayQueryGetIntersectionObjectRayDirectionKHR"; - case OpRayQueryGetIntersectionObjectRayOriginKHR: return "OpRayQueryGetIntersectionObjectRayOriginKHR"; - case OpRayQueryGetWorldRayDirectionKHR: return "OpRayQueryGetWorldRayDirectionKHR"; - case OpRayQueryGetWorldRayOriginKHR: return "OpRayQueryGetWorldRayOriginKHR"; - case OpRayQueryGetIntersectionObjectToWorldKHR: return "OpRayQueryGetIntersectionObjectToWorldKHR"; - case OpRayQueryGetIntersectionWorldToObjectKHR: return "OpRayQueryGetIntersectionWorldToObjectKHR"; - case OpRayQueryGetIntersectionTriangleVertexPositionsKHR: return "OpRayQueryGetIntersectionTriangleVertexPositionsKHR"; - - case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV"; - case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV"; - case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV"; - case OpCooperativeMatrixMulAddNV: return "OpCooperativeMatrixMulAddNV"; - case OpCooperativeMatrixLengthNV: return "OpCooperativeMatrixLengthNV"; - case OpTypeCooperativeMatrixKHR: return "OpTypeCooperativeMatrixKHR"; - case OpCooperativeMatrixLoadKHR: return "OpCooperativeMatrixLoadKHR"; - case OpCooperativeMatrixStoreKHR: return "OpCooperativeMatrixStoreKHR"; - case OpCooperativeMatrixMulAddKHR: return "OpCooperativeMatrixMulAddKHR"; - case OpCooperativeMatrixLengthKHR: return "OpCooperativeMatrixLengthKHR"; - case OpDemoteToHelperInvocationEXT: return "OpDemoteToHelperInvocationEXT"; - case OpIsHelperInvocationEXT: return "OpIsHelperInvocationEXT"; - - case OpCooperativeMatrixConvertNV: return "OpCooperativeMatrixConvertNV"; - case OpCooperativeMatrixTransposeNV: return "OpCooperativeMatrixTransposeNV"; - case OpCooperativeMatrixReduceNV: return "OpCooperativeMatrixReduceNV"; - case OpCooperativeMatrixLoadTensorNV: return "OpCooperativeMatrixLoadTensorNV"; - case OpCooperativeMatrixStoreTensorNV: return "OpCooperativeMatrixStoreTensorNV"; - case OpCooperativeMatrixPerElementOpNV: return "OpCooperativeMatrixPerElementOpNV"; - case OpTypeTensorLayoutNV: return "OpTypeTensorLayoutNV"; - case OpTypeTensorViewNV: return "OpTypeTensorViewNV"; - case OpCreateTensorLayoutNV: return "OpCreateTensorLayoutNV"; - case OpTensorLayoutSetBlockSizeNV: return "OpTensorLayoutSetBlockSizeNV"; - case OpTensorLayoutSetDimensionNV: return "OpTensorLayoutSetDimensionNV"; - case OpTensorLayoutSetStrideNV: return "OpTensorLayoutSetStrideNV"; - case OpTensorLayoutSliceNV: return "OpTensorLayoutSliceNV"; - case OpTensorLayoutSetClampValueNV: return "OpTensorLayoutSetClampValueNV"; - case OpCreateTensorViewNV: return "OpCreateTensorViewNV"; - case OpTensorViewSetDimensionNV: return "OpTensorViewSetDimensionNV"; - case OpTensorViewSetStrideNV: return "OpTensorViewSetStrideNV"; - case OpTensorViewSetClipNV: return "OpTensorViewSetClipNV"; - - case OpBeginInvocationInterlockEXT: return "OpBeginInvocationInterlockEXT"; - case OpEndInvocationInterlockEXT: return "OpEndInvocationInterlockEXT"; - - case OpTypeHitObjectNV: return "OpTypeHitObjectNV"; - case OpHitObjectTraceRayNV: return "OpHitObjectTraceRayNV"; - case OpHitObjectTraceRayMotionNV: return "OpHitObjectTraceRayMotionNV"; - case OpHitObjectRecordHitNV: return "OpHitObjectRecordHitNV"; - case OpHitObjectRecordHitMotionNV: return "OpHitObjectRecordHitMotionNV"; - case OpHitObjectRecordHitWithIndexNV: return "OpHitObjectRecordHitWithIndexNV"; - case OpHitObjectRecordHitWithIndexMotionNV: return "OpHitObjectRecordHitWithIndexMotionNV"; - case OpHitObjectRecordMissNV: return "OpHitObjectRecordMissNV"; - case OpHitObjectRecordMissMotionNV: return "OpHitObjectRecordMissMotionNV"; - case OpHitObjectRecordEmptyNV: return "OpHitObjectRecordEmptyNV"; - case OpHitObjectExecuteShaderNV: return "OpHitObjectExecuteShaderNV"; - case OpReorderThreadWithHintNV: return "OpReorderThreadWithHintNV"; - case OpReorderThreadWithHitObjectNV: return "OpReorderThreadWithHitObjectNV"; - case OpHitObjectGetCurrentTimeNV: return "OpHitObjectGetCurrentTimeNV"; - case OpHitObjectGetAttributesNV: return "OpHitObjectGetAttributesNV"; - case OpHitObjectGetHitKindNV: return "OpHitObjectGetFrontFaceNV"; - case OpHitObjectGetPrimitiveIndexNV: return "OpHitObjectGetPrimitiveIndexNV"; - case OpHitObjectGetGeometryIndexNV: return "OpHitObjectGetGeometryIndexNV"; - case OpHitObjectGetInstanceIdNV: return "OpHitObjectGetInstanceIdNV"; - case OpHitObjectGetInstanceCustomIndexNV: return "OpHitObjectGetInstanceCustomIndexNV"; - case OpHitObjectGetObjectRayDirectionNV: return "OpHitObjectGetObjectRayDirectionNV"; - case OpHitObjectGetObjectRayOriginNV: return "OpHitObjectGetObjectRayOriginNV"; - case OpHitObjectGetWorldRayDirectionNV: return "OpHitObjectGetWorldRayDirectionNV"; - case OpHitObjectGetWorldRayOriginNV: return "OpHitObjectGetWorldRayOriginNV"; - case OpHitObjectGetWorldToObjectNV: return "OpHitObjectGetWorldToObjectNV"; - case OpHitObjectGetObjectToWorldNV: return "OpHitObjectGetObjectToWorldNV"; - case OpHitObjectGetRayTMaxNV: return "OpHitObjectGetRayTMaxNV"; - case OpHitObjectGetRayTMinNV: return "OpHitObjectGetRayTMinNV"; - case OpHitObjectIsEmptyNV: return "OpHitObjectIsEmptyNV"; - case OpHitObjectIsHitNV: return "OpHitObjectIsHitNV"; - case OpHitObjectIsMissNV: return "OpHitObjectIsMissNV"; - case OpHitObjectGetShaderBindingTableRecordIndexNV: return "OpHitObjectGetShaderBindingTableRecordIndexNV"; - case OpHitObjectGetShaderRecordBufferHandleNV: return "OpHitObjectGetShaderRecordBufferHandleNV"; - - case OpFetchMicroTriangleVertexBarycentricNV: return "OpFetchMicroTriangleVertexBarycentricNV"; - case OpFetchMicroTriangleVertexPositionNV: return "OpFetchMicroTriangleVertexPositionNV"; - - case OpColorAttachmentReadEXT: return "OpColorAttachmentReadEXT"; - case OpDepthAttachmentReadEXT: return "OpDepthAttachmentReadEXT"; - case OpStencilAttachmentReadEXT: return "OpStencilAttachmentReadEXT"; - - case OpImageSampleWeightedQCOM: return "OpImageSampleWeightedQCOM"; - case OpImageBoxFilterQCOM: return "OpImageBoxFilterQCOM"; - case OpImageBlockMatchSADQCOM: return "OpImageBlockMatchSADQCOM"; - case OpImageBlockMatchSSDQCOM: return "OpImageBlockMatchSSDQCOM"; - case OpImageBlockMatchWindowSSDQCOM: return "OpImageBlockMatchWindowSSDQCOM"; - case OpImageBlockMatchWindowSADQCOM: return "OpImageBlockMatchWindowSADQCOM"; - case OpImageBlockMatchGatherSSDQCOM: return "OpImageBlockMatchGatherSSDQCOM"; - case OpImageBlockMatchGatherSADQCOM: return "OpImageBlockMatchGatherSADQCOM"; - - case OpConstantCompositeReplicateEXT: return "OpConstantCompositeReplicateEXT"; - case OpSpecConstantCompositeReplicateEXT: return "OpSpecConstantCompositeReplicateEXT"; - case OpCompositeConstructReplicateEXT: return "OpCompositeConstructReplicateEXT"; - - default: - return "Bad"; - } -} - -// The set of objects that hold all the instruction/operand -// parameterization information. -InstructionParameters InstructionDesc[OpCodeMask + 1]; -OperandParameters ExecutionModeOperands[ExecutionModeCeiling]; -OperandParameters DecorationOperands[DecorationCeiling]; - -EnumDefinition OperandClassParams[OperandCount]; -EnumParameters ExecutionModeParams[ExecutionModeCeiling]; -EnumParameters ImageOperandsParams[ImageOperandsCeiling]; -EnumParameters DecorationParams[DecorationCeiling]; -EnumParameters LoopControlParams[FunctionControlCeiling]; -EnumParameters SelectionControlParams[SelectControlCeiling]; -EnumParameters FunctionControlParams[FunctionControlCeiling]; -EnumParameters MemoryAccessParams[MemoryAccessCeiling]; -EnumParameters CooperativeMatrixOperandsParams[CooperativeMatrixOperandsCeiling]; -EnumParameters TensorAddressingOperandsParams[TensorAddressingOperandsCeiling]; - -// Set up all the parameterizing descriptions of the opcodes, operands, etc. -void Parameterize() -{ - // only do this once. - static std::once_flag initialized; - std::call_once(initialized, [](){ - - // Exceptions to having a result and a resulting type . - // (Everything is initialized to have both). - - InstructionDesc[OpNop].setResultAndType(false, false); - InstructionDesc[OpSource].setResultAndType(false, false); - InstructionDesc[OpSourceContinued].setResultAndType(false, false); - InstructionDesc[OpSourceExtension].setResultAndType(false, false); - InstructionDesc[OpExtension].setResultAndType(false, false); - InstructionDesc[OpExtInstImport].setResultAndType(true, false); - InstructionDesc[OpCapability].setResultAndType(false, false); - InstructionDesc[OpMemoryModel].setResultAndType(false, false); - InstructionDesc[OpEntryPoint].setResultAndType(false, false); - InstructionDesc[OpExecutionMode].setResultAndType(false, false); - InstructionDesc[OpExecutionModeId].setResultAndType(false, false); - InstructionDesc[OpTypeVoid].setResultAndType(true, false); - InstructionDesc[OpTypeBool].setResultAndType(true, false); - InstructionDesc[OpTypeInt].setResultAndType(true, false); - InstructionDesc[OpTypeFloat].setResultAndType(true, false); - InstructionDesc[OpTypeVector].setResultAndType(true, false); - InstructionDesc[OpTypeMatrix].setResultAndType(true, false); - InstructionDesc[OpTypeImage].setResultAndType(true, false); - InstructionDesc[OpTypeSampler].setResultAndType(true, false); - InstructionDesc[OpTypeSampledImage].setResultAndType(true, false); - InstructionDesc[OpTypeArray].setResultAndType(true, false); - InstructionDesc[OpTypeRuntimeArray].setResultAndType(true, false); - InstructionDesc[OpTypeStruct].setResultAndType(true, false); - InstructionDesc[OpTypeOpaque].setResultAndType(true, false); - InstructionDesc[OpTypePointer].setResultAndType(true, false); - InstructionDesc[OpTypeForwardPointer].setResultAndType(false, false); - InstructionDesc[OpTypeFunction].setResultAndType(true, false); - InstructionDesc[OpTypeEvent].setResultAndType(true, false); - InstructionDesc[OpTypeDeviceEvent].setResultAndType(true, false); - InstructionDesc[OpTypeReserveId].setResultAndType(true, false); - InstructionDesc[OpTypeQueue].setResultAndType(true, false); - InstructionDesc[OpTypePipe].setResultAndType(true, false); - InstructionDesc[OpFunctionEnd].setResultAndType(false, false); - InstructionDesc[OpStore].setResultAndType(false, false); - InstructionDesc[OpImageWrite].setResultAndType(false, false); - InstructionDesc[OpDecorationGroup].setResultAndType(true, false); - InstructionDesc[OpDecorate].setResultAndType(false, false); - InstructionDesc[OpDecorateId].setResultAndType(false, false); - InstructionDesc[OpDecorateStringGOOGLE].setResultAndType(false, false); - InstructionDesc[OpMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpMemberDecorateStringGOOGLE].setResultAndType(false, false); - InstructionDesc[OpGroupDecorate].setResultAndType(false, false); - InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpName].setResultAndType(false, false); - InstructionDesc[OpMemberName].setResultAndType(false, false); - InstructionDesc[OpString].setResultAndType(true, false); - InstructionDesc[OpLine].setResultAndType(false, false); - InstructionDesc[OpNoLine].setResultAndType(false, false); - InstructionDesc[OpCopyMemory].setResultAndType(false, false); - InstructionDesc[OpCopyMemorySized].setResultAndType(false, false); - InstructionDesc[OpEmitVertex].setResultAndType(false, false); - InstructionDesc[OpEndPrimitive].setResultAndType(false, false); - InstructionDesc[OpEmitStreamVertex].setResultAndType(false, false); - InstructionDesc[OpEndStreamPrimitive].setResultAndType(false, false); - InstructionDesc[OpControlBarrier].setResultAndType(false, false); - InstructionDesc[OpMemoryBarrier].setResultAndType(false, false); - InstructionDesc[OpAtomicStore].setResultAndType(false, false); - InstructionDesc[OpLoopMerge].setResultAndType(false, false); - InstructionDesc[OpSelectionMerge].setResultAndType(false, false); - InstructionDesc[OpLabel].setResultAndType(true, false); - InstructionDesc[OpBranch].setResultAndType(false, false); - InstructionDesc[OpBranchConditional].setResultAndType(false, false); - InstructionDesc[OpSwitch].setResultAndType(false, false); - InstructionDesc[OpKill].setResultAndType(false, false); - InstructionDesc[OpTerminateInvocation].setResultAndType(false, false); - InstructionDesc[OpReturn].setResultAndType(false, false); - InstructionDesc[OpReturnValue].setResultAndType(false, false); - InstructionDesc[OpUnreachable].setResultAndType(false, false); - InstructionDesc[OpLifetimeStart].setResultAndType(false, false); - InstructionDesc[OpLifetimeStop].setResultAndType(false, false); - InstructionDesc[OpCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCaptureEventProfilingInfo].setResultAndType(false, false); - InstructionDesc[OpSetUserEventStatus].setResultAndType(false, false); - InstructionDesc[OpRetainEvent].setResultAndType(false, false); - InstructionDesc[OpReleaseEvent].setResultAndType(false, false); - InstructionDesc[OpGroupWaitEvents].setResultAndType(false, false); - InstructionDesc[OpAtomicFlagClear].setResultAndType(false, false); - InstructionDesc[OpModuleProcessed].setResultAndType(false, false); - InstructionDesc[OpTypeCooperativeMatrixNV].setResultAndType(true, false); - InstructionDesc[OpCooperativeMatrixStoreNV].setResultAndType(false, false); - InstructionDesc[OpTypeCooperativeMatrixKHR].setResultAndType(true, false); - InstructionDesc[OpCooperativeMatrixStoreKHR].setResultAndType(false, false); - InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false); - InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false); - InstructionDesc[OpAssumeTrueKHR].setResultAndType(false, false); - InstructionDesc[OpTypeTensorLayoutNV].setResultAndType(true, false); - InstructionDesc[OpTypeTensorViewNV].setResultAndType(true, false); - InstructionDesc[OpCooperativeMatrixStoreTensorNV].setResultAndType(false, false); - // Specific additional context-dependent operands - - ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <>'"); - - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeOutputVertices].push(OperandLiteralNumber, "'Vertex count'"); - ExecutionModeOperands[ExecutionModeVecTypeHint].push(OperandLiteralNumber, "'Vector type'"); - - DecorationOperands[DecorationStream].push(OperandLiteralNumber, "'Stream Number'"); - DecorationOperands[DecorationLocation].push(OperandLiteralNumber, "'Location'"); - DecorationOperands[DecorationComponent].push(OperandLiteralNumber, "'Component'"); - DecorationOperands[DecorationIndex].push(OperandLiteralNumber, "'Index'"); - DecorationOperands[DecorationBinding].push(OperandLiteralNumber, "'Binding Point'"); - DecorationOperands[DecorationDescriptorSet].push(OperandLiteralNumber, "'Descriptor Set'"); - DecorationOperands[DecorationOffset].push(OperandLiteralNumber, "'Byte Offset'"); - DecorationOperands[DecorationXfbBuffer].push(OperandLiteralNumber, "'XFB Buffer Number'"); - DecorationOperands[DecorationXfbStride].push(OperandLiteralNumber, "'XFB Stride'"); - DecorationOperands[DecorationArrayStride].push(OperandLiteralNumber, "'Array Stride'"); - DecorationOperands[DecorationMatrixStride].push(OperandLiteralNumber, "'Matrix Stride'"); - DecorationOperands[DecorationBuiltIn].push(OperandLiteralNumber, "See <>"); - DecorationOperands[DecorationFPRoundingMode].push(OperandFPRoundingMode, "'Floating-Point Rounding Mode'"); - DecorationOperands[DecorationFPFastMathMode].push(OperandFPFastMath, "'Fast-Math Mode'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLiteralString, "'Name'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLinkageType, "'Linkage Type'"); - DecorationOperands[DecorationFuncParamAttr].push(OperandFuncParamAttr, "'Function Parameter Attribute'"); - DecorationOperands[DecorationSpecId].push(OperandLiteralNumber, "'Specialization Constant ID'"); - DecorationOperands[DecorationInputAttachmentIndex].push(OperandLiteralNumber, "'Attachment Index'"); - DecorationOperands[DecorationAlignment].push(OperandLiteralNumber, "'Alignment'"); - - OperandClassParams[OperandSource].set(0, SourceString, nullptr); - OperandClassParams[OperandExecutionModel].set(0, ExecutionModelString, nullptr); - OperandClassParams[OperandAddressing].set(0, AddressingString, nullptr); - OperandClassParams[OperandMemory].set(0, MemoryString, nullptr); - OperandClassParams[OperandExecutionMode].set(ExecutionModeCeiling, ExecutionModeString, ExecutionModeParams); - OperandClassParams[OperandExecutionMode].setOperands(ExecutionModeOperands); - OperandClassParams[OperandStorage].set(0, StorageClassString, nullptr); - OperandClassParams[OperandDimensionality].set(0, DimensionString, nullptr); - OperandClassParams[OperandSamplerAddressingMode].set(0, SamplerAddressingModeString, nullptr); - OperandClassParams[OperandSamplerFilterMode].set(0, SamplerFilterModeString, nullptr); - OperandClassParams[OperandSamplerImageFormat].set(0, ImageFormatString, nullptr); - OperandClassParams[OperandImageChannelOrder].set(0, ImageChannelOrderString, nullptr); - OperandClassParams[OperandImageChannelDataType].set(0, ImageChannelDataTypeString, nullptr); - OperandClassParams[OperandImageOperands].set(ImageOperandsCeiling, ImageOperandsString, ImageOperandsParams, true); - OperandClassParams[OperandFPFastMath].set(0, FPFastMathString, nullptr, true); - OperandClassParams[OperandFPRoundingMode].set(0, FPRoundingModeString, nullptr); - OperandClassParams[OperandLinkageType].set(0, LinkageTypeString, nullptr); - OperandClassParams[OperandFuncParamAttr].set(0, FuncParamAttrString, nullptr); - OperandClassParams[OperandAccessQualifier].set(0, AccessQualifierString, nullptr); - OperandClassParams[OperandDecoration].set(DecorationCeiling, DecorationString, DecorationParams); - OperandClassParams[OperandDecoration].setOperands(DecorationOperands); - OperandClassParams[OperandBuiltIn].set(0, BuiltInString, nullptr); - OperandClassParams[OperandSelect].set(SelectControlCeiling, SelectControlString, SelectionControlParams, true); - OperandClassParams[OperandLoop].set(LoopControlCeiling, LoopControlString, LoopControlParams, true); - OperandClassParams[OperandFunction].set(FunctionControlCeiling, FunctionControlString, FunctionControlParams, true); - OperandClassParams[OperandMemorySemantics].set(0, MemorySemanticsString, nullptr, true); - OperandClassParams[OperandMemoryAccess].set(MemoryAccessCeiling, MemoryAccessString, MemoryAccessParams, true); - OperandClassParams[OperandScope].set(0, ScopeString, nullptr); - OperandClassParams[OperandGroupOperation].set(0, GroupOperationString, nullptr); - OperandClassParams[OperandKernelEnqueueFlags].set(0, KernelEnqueueFlagsString, nullptr); - OperandClassParams[OperandKernelProfilingInfo].set(0, KernelProfilingInfoString, nullptr, true); - OperandClassParams[OperandCapability].set(0, CapabilityString, nullptr); - OperandClassParams[OperandCooperativeMatrixOperands].set(CooperativeMatrixOperandsCeiling, CooperativeMatrixOperandsString, CooperativeMatrixOperandsParams, true); - OperandClassParams[OperandTensorAddressingOperands].set(TensorAddressingOperandsCeiling, TensorAddressingOperandsString, TensorAddressingOperandsParams, true); - OperandClassParams[OperandOpcode].set(OpCodeMask + 1, OpcodeString, nullptr); - - // set name of operator, an initial set of style operands, and the description - - InstructionDesc[OpSource].operands.push(OperandSource, ""); - InstructionDesc[OpSource].operands.push(OperandLiteralNumber, "'Version'"); - InstructionDesc[OpSource].operands.push(OperandId, "'File'", true); - InstructionDesc[OpSource].operands.push(OperandLiteralString, "'Source'", true); - - InstructionDesc[OpSourceContinued].operands.push(OperandLiteralString, "'Continued Source'"); - - InstructionDesc[OpSourceExtension].operands.push(OperandLiteralString, "'Extension'"); - - InstructionDesc[OpName].operands.push(OperandId, "'Target'"); - InstructionDesc[OpName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpMemberName].operands.push(OperandId, "'Type'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpString].operands.push(OperandLiteralString, "'String'"); - - InstructionDesc[OpLine].operands.push(OperandId, "'File'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Line'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Column'"); - - InstructionDesc[OpExtension].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpExtInstImport].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpCapability].operands.push(OperandCapability, "'Capability'"); - - InstructionDesc[OpMemoryModel].operands.push(OperandAddressing, ""); - InstructionDesc[OpMemoryModel].operands.push(OperandMemory, ""); - - InstructionDesc[OpEntryPoint].operands.push(OperandExecutionModel, ""); - InstructionDesc[OpEntryPoint].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpEntryPoint].operands.push(OperandLiteralString, "'Name'"); - InstructionDesc[OpEntryPoint].operands.push(OperandVariableIds, "'Interface'"); - - InstructionDesc[OpExecutionMode].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'"); - InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <>"); - - InstructionDesc[OpExecutionModeId].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpExecutionModeId].operands.push(OperandExecutionMode, "'Mode'"); - InstructionDesc[OpExecutionModeId].operands.push(OperandVariableIds, "See <>"); - - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'"); - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'"); - - InstructionDesc[OpTypeFloat].operands.push(OperandLiteralNumber, "'Width'"); - - InstructionDesc[OpTypeVector].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeVector].operands.push(OperandLiteralNumber, "'Component Count'"); - - InstructionDesc[OpTypeMatrix].operands.push(OperandId, "'Column Type'"); - InstructionDesc[OpTypeMatrix].operands.push(OperandLiteralNumber, "'Column Count'"); - - InstructionDesc[OpTypeImage].operands.push(OperandId, "'Sampled Type'"); - InstructionDesc[OpTypeImage].operands.push(OperandDimensionality, ""); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Depth'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Arrayed'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'MS'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Sampled'"); - InstructionDesc[OpTypeImage].operands.push(OperandSamplerImageFormat, ""); - InstructionDesc[OpTypeImage].operands.push(OperandAccessQualifier, "", true); - - InstructionDesc[OpTypeSampledImage].operands.push(OperandId, "'Image Type'"); - - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Element Type'"); - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Length'"); - - InstructionDesc[OpTypeRuntimeArray].operands.push(OperandId, "'Element Type'"); - - InstructionDesc[OpTypeStruct].operands.push(OperandVariableIds, "'Member 0 type', +\n'member 1 type', +\n..."); - - InstructionDesc[OpTypeOpaque].operands.push(OperandLiteralString, "The name of the opaque type."); - - InstructionDesc[OpTypePointer].operands.push(OperandStorage, ""); - InstructionDesc[OpTypePointer].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpTypeForwardPointer].operands.push(OperandId, "'Pointer Type'"); - InstructionDesc[OpTypeForwardPointer].operands.push(OperandStorage, ""); - - InstructionDesc[OpTypePipe].operands.push(OperandAccessQualifier, "'Qualifier'"); - - InstructionDesc[OpTypeFunction].operands.push(OperandId, "'Return Type'"); - InstructionDesc[OpTypeFunction].operands.push(OperandVariableIds, "'Parameter 0 Type', +\n'Parameter 1 Type', +\n..."); - - InstructionDesc[OpConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerAddressingMode, ""); - InstructionDesc[OpConstantSampler].operands.push(OperandLiteralNumber, "'Param'"); - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerFilterMode, ""); - - InstructionDesc[OpSpecConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpSpecConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpSpecConstantOp].operands.push(OperandLiteralNumber, "'Opcode'"); - InstructionDesc[OpSpecConstantOp].operands.push(OperandVariableIds, "'Operands'"); - - InstructionDesc[OpVariable].operands.push(OperandStorage, ""); - InstructionDesc[OpVariable].operands.push(OperandId, "'Initializer'", true); - - InstructionDesc[OpFunction].operands.push(OperandFunction, ""); - InstructionDesc[OpFunction].operands.push(OperandId, "'Function Type'"); - - InstructionDesc[OpFunctionCall].operands.push(OperandId, "'Function'"); - InstructionDesc[OpFunctionCall].operands.push(OperandVariableIds, "'Argument 0', +\n'Argument 1', +\n..."); - - InstructionDesc[OpExtInst].operands.push(OperandId, "'Set'"); - InstructionDesc[OpExtInst].operands.push(OperandLiteralNumber, "'Instruction'"); - InstructionDesc[OpExtInst].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n..."); - - InstructionDesc[OpExtInstWithForwardRefsKHR].operands.push(OperandId, "'Set'"); - InstructionDesc[OpExtInstWithForwardRefsKHR].operands.push(OperandLiteralNumber, "'Instruction'"); - InstructionDesc[OpExtInstWithForwardRefsKHR].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n..."); - - InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true); - InstructionDesc[OpLoad].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpLoad].operands.push(OperandId, "", true); - - InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpStore].operands.push(OperandId, "'Object'"); - InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true); - InstructionDesc[OpStore].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpStore].operands.push(OperandId, "", true); - - InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'"); - - InstructionDesc[OpDecorate].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpDecorateId].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorateId].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorateId].operands.push(OperandVariableIds, "See <>."); - - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'"); - - InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'"); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'"); - - InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'"); - - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandVariableIdLiteral, "'Targets'"); - - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Component'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 2'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandVariableLiterals, "'Components'"); - - InstructionDesc[OpCompositeConstruct].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpCompositeExtract].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeExtract].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCopyObject].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemory].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Size'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Image'"); - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Sampler'"); - - InstructionDesc[OpImage].operands.push(OperandId, "'Sampled Image'"); - - InstructionDesc[OpImageRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageRead].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Texel'"); - InstructionDesc[OpImageWrite].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageWrite].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageFetch].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageDrefGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseFetch].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseRead].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseTexelsResident].operands.push(OperandId, "'Resident Code'"); - - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Level of Detail'"); - - InstructionDesc[OpImageQuerySize].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Coordinate'"); - - InstructionDesc[OpImageQueryLevels].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQuerySamples].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryFormat].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryOrder].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpSNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpFNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpAny].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpAll].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpConvertFToU].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertFToS].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertSToF].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpConvertUToF].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpUConvert].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpSConvert].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpFConvert].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpSatConvertSToU].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpSatConvertUToS].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpConvertPtrToU].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpConvertUToPtr].operands.push(OperandId, "'Integer Value'"); - - InstructionDesc[OpPtrCastToGeneric].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpGenericCastToPtr].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandStorage, "'Storage'"); - - InstructionDesc[OpGenericPtrMemSemantics].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpBitcast].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpQuantizeToF16].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpTranspose].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpCopyLogical].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpIsNan].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsInf].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsFinite].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsNormal].operands.push(OperandId, "'x'"); - - InstructionDesc[OpSignBitSet].operands.push(OperandId, "'x'"); - - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'x'"); - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'y'"); - - InstructionDesc[OpOrdered].operands.push(OperandId, "'x'"); - InstructionDesc[OpOrdered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpUnordered].operands.push(OperandId, "'x'"); - InstructionDesc[OpUnordered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpArrayLength].operands.push(OperandId, "'Structure'"); - InstructionDesc[OpArrayLength].operands.push(OperandLiteralNumber, "'Array member'"); - - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'LeftMatrix'"); - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'RightMatrix'"); - - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Insert'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitReverse].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpBitCount].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpSelect].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 1'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 2'"); - - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpDPdx].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdy].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidth].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpEmitStreamVertex].operands.push(OperandId, "'Stream'"); - - InstructionDesc[OpEndStreamPrimitive].operands.push(OperandId, "'Stream'"); - - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpControlBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpMemoryBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpMemoryBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Sample'"); - - InstructionDesc[OpAtomicLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicStore].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicStore].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Comparator'"); - - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Comparator'"); - - InstructionDesc[OpAtomicIIncrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIDecrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAssumeTrueKHR].operands.push(OperandId, "'Condition'"); - - InstructionDesc[OpExpectKHR].operands.push(OperandId, "'Value'"); - InstructionDesc[OpExpectKHR].operands.push(OperandId, "'ExpectedValue'"); - - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicOr].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicOr].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicXor].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicXor].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicFlagClear].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'"); - InstructionDesc[OpLoopMerge].operands.push(OperandLoop, ""); - InstructionDesc[OpLoopMerge].operands.push(OperandOptionalLiteral, ""); - - InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpSelectionMerge].operands.push(OperandSelect, ""); - - InstructionDesc[OpBranch].operands.push(OperandId, "'Target Label'"); - - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'True Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'False Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandVariableLiterals, "'Branch weights'"); - - InstructionDesc[OpSwitch].operands.push(OperandId, "'Selector'"); - InstructionDesc[OpSwitch].operands.push(OperandId, "'Default'"); - InstructionDesc[OpSwitch].operands.push(OperandVariableLiteralId, "'Target'"); - - - InstructionDesc[OpReturnValue].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpLifetimeStart].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStart].operands.push(OperandLiteralNumber, "'Size'"); - - InstructionDesc[OpLifetimeStop].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStop].operands.push(OperandLiteralNumber, "'Size'"); - - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Destination'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Source'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Num Elements'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGroupWaitEvents].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Events List'"); - - InstructionDesc[OpGroupAll].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAll].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupAny].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAny].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'Value'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'LocalId'"); - - InstructionDesc[OpGroupIAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMin].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMax].operands.push(OperandId, "X"); - - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpIsValidReserveId].operands.push(OperandId, "'Reserve Id'"); - - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'LocalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkOffset'"); - - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Event'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Profiling Info'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Event'"); - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Status'"); - - InstructionDesc[OpIsValidEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpRetainEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpReleaseEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Flags'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Ret Event'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Align'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandVariableIds, "'Local Size'"); - - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Ret Event'"); - - InstructionDesc[OpGroupNonUniformElect].operands.push(OperandScope, "'Execution'"); - - InstructionDesc[OpGroupNonUniformAll].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAll].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformAny].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAny].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "ID"); - - InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "Bit"); - - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "'Id'"); - - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "Mask"); - - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "Offset"); - - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "Offset"); - - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "'Id'"); - - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "'Direction'"); - - InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupFirstInvocationKHR].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'X'"); - InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'Delta'"); - InstructionDesc[OpGroupNonUniformRotateKHR].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'"); - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpModuleProcessed].operands.push(OperandLiteralString, "'process'"); - - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Coordinate'"); - - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Fragment Index'"); - - InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformQuadAllKHR].operands.push(OperandId, "'Predicate'"); - InstructionDesc[OpGroupNonUniformQuadAnyKHR].operands.push(OperandId, "'Predicate'"); - InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); - - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpTraceNV].setResultAndType(false, false); - - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Flags'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Cull Mask'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Origin'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Direction'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Time'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpTraceRayMotionNV].setResultAndType(false, false); - - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpTraceRayKHR].setResultAndType(false, false); - - InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'"); - InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'"); - - InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false); - - InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false); - - InstructionDesc[OpTerminateRayNV].setResultAndType(false, false); - - InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false); - - InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index"); - InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID"); - InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false); - - InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index"); - InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData"); - InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false); - - InstructionDesc[OpConvertUToAccelerationStructureKHR].operands.push(OperandId, "Value"); - InstructionDesc[OpConvertUToAccelerationStructureKHR].setResultAndType(true, true); - - // Ray Query - InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); - InstructionDesc[OpTypeRayQueryKHR].setResultAndType(true, false); - - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'"); - InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'"); - InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].setResultAndType(true, true); - - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coarse'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Index Offset'"); - InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Packed Indices'"); - - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountX'"); - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountY'"); - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountZ'"); - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpEmitMeshTasksEXT].setResultAndType(false, false); - - InstructionDesc[OpSetMeshOutputsEXT].operands.push(OperandId, "'vertexCount'"); - InstructionDesc[OpSetMeshOutputsEXT].operands.push(OperandId, "'primitiveCount'"); - InstructionDesc[OpSetMeshOutputsEXT].setResultAndType(false, false); - - - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Scope'"); - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Rows'"); - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Columns'"); - - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Column Major'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Column Major'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'A'"); - InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'B'"); - InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'C'"); - - InstructionDesc[OpCooperativeMatrixLengthNV].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Scope'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Rows'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Columns'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Use'"); - - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "'Memory Layout'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Memory Layout'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandId, "'A'"); - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandId, "'B'"); - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandId, "'C'"); - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandCooperativeMatrixOperands, "'Cooperative Matrix Operands'", true); - - InstructionDesc[OpCooperativeMatrixLengthKHR].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpDemoteToHelperInvocationEXT].setResultAndType(false, false); - - InstructionDesc[OpReadClockKHR].operands.push(OperandScope, "'Scope'"); - - InstructionDesc[OpTypeHitObjectNV].setResultAndType(true, false); - - InstructionDesc[OpHitObjectGetShaderRecordBufferHandleNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetShaderRecordBufferHandleNV].setResultAndType(true, true); - - InstructionDesc[OpReorderThreadWithHintNV].operands.push(OperandId, "'Hint'"); - InstructionDesc[OpReorderThreadWithHintNV].operands.push(OperandId, "'Bits'"); - InstructionDesc[OpReorderThreadWithHintNV].setResultAndType(false, false); - - InstructionDesc[OpReorderThreadWithHitObjectNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpReorderThreadWithHitObjectNV].operands.push(OperandId, "'Hint'"); - InstructionDesc[OpReorderThreadWithHitObjectNV].operands.push(OperandId, "'Bits'"); - InstructionDesc[OpReorderThreadWithHitObjectNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectGetCurrentTimeNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetCurrentTimeNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetHitKindNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetHitKindNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetPrimitiveIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetPrimitiveIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetGeometryIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetGeometryIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetInstanceIdNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetInstanceIdNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetInstanceCustomIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetInstanceCustomIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetObjectRayDirectionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetObjectRayDirectionNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetObjectRayOriginNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetObjectRayOriginNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetWorldRayDirectionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetWorldRayDirectionNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetWorldRayOriginNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetWorldRayOriginNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetWorldToObjectNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetWorldToObjectNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetObjectToWorldNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetObjectToWorldNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetRayTMaxNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetRayTMaxNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetRayTMinNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetRayTMinNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetShaderBindingTableRecordIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetShaderBindingTableRecordIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectIsEmptyNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectIsEmptyNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectIsHitNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectIsHitNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectIsMissNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectIsMissNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetAttributesNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetAttributesNV].operands.push(OperandId, "'HitObjectAttribute'"); - InstructionDesc[OpHitObjectGetAttributesNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectExecuteShaderNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectExecuteShaderNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpHitObjectExecuteShaderNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Current Time'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'SBT Record Index'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'SBT Record Index'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Current Time'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'SBT Index'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordMissNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'SBT Index'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'Current Time'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordEmptyNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordEmptyNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'RayFlags'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Cullmask'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpHitObjectTraceRayNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'RayFlags'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Cullmask'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Time'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].setResultAndType(false, false); - - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Instance ID'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Geometry Index'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Primitive Index'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Barycentrics'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].setResultAndType(true, true); - - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Instance ID'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Geometry Index'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Primitive Index'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Barycentrics'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].setResultAndType(true, true); - - InstructionDesc[OpColorAttachmentReadEXT].operands.push(OperandId, "'Attachment'"); - InstructionDesc[OpColorAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); - InstructionDesc[OpStencilAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); - InstructionDesc[OpDepthAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); - - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'source texture'"); - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'texture coordinates'"); - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'weights texture'"); - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleWeightedQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'source texture'"); - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'texture coordinates'"); - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'box size'"); - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBoxFilterQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchSADQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchSSDQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchWindowSSDQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchWindowSSDQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchWindowSSDQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchWindowSSDQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchWindowSSDQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchWindowSSDQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchWindowSSDQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchWindowSADQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchWindowSADQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchWindowSADQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchWindowSADQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchWindowSADQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchWindowSADQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchWindowSADQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchGatherSSDQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchGatherSSDQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchGatherSSDQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchGatherSSDQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchGatherSSDQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchGatherSSDQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchGatherSSDQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchGatherSADQCOM].setResultAndType(true, true); - - InstructionDesc[OpConstantCompositeReplicateEXT].operands.push(OperandId, "'Value'"); - InstructionDesc[OpSpecConstantCompositeReplicateEXT].operands.push(OperandId, "'Value'"); - InstructionDesc[OpCompositeConstructReplicateEXT].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpCooperativeMatrixConvertNV].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpCooperativeMatrixTransposeNV].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpCooperativeMatrixReduceNV].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpCooperativeMatrixReduceNV].operands.push(OperandLiteralNumber, "'ReduceMask'"); - InstructionDesc[OpCooperativeMatrixReduceNV].operands.push(OperandId, "'CombineFunc'"); - - InstructionDesc[OpCooperativeMatrixPerElementOpNV].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpCooperativeMatrixPerElementOpNV].operands.push(OperandId, "'Operation'"); - InstructionDesc[OpCooperativeMatrixPerElementOpNV].operands.push(OperandVariableIds, "'Operands'"); - - InstructionDesc[OpCooperativeMatrixLoadTensorNV].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixLoadTensorNV].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCooperativeMatrixLoadTensorNV].operands.push(OperandId, "'TensorLayout'"); - InstructionDesc[OpCooperativeMatrixLoadTensorNV].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixLoadTensorNV].operands.push(OperandTensorAddressingOperands, "'Tensor Addressing Operands'"); - - InstructionDesc[OpCooperativeMatrixStoreTensorNV].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixStoreTensorNV].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCooperativeMatrixStoreTensorNV].operands.push(OperandId, "'TensorLayout'"); - InstructionDesc[OpCooperativeMatrixStoreTensorNV].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixStoreTensorNV].operands.push(OperandTensorAddressingOperands, "'Tensor Addressing Operands'"); - - InstructionDesc[OpCooperativeMatrixReduceNV].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpCooperativeMatrixReduceNV].operands.push(OperandLiteralNumber, "'ReduceMask'"); - - InstructionDesc[OpTypeTensorLayoutNV].operands.push(OperandId, "'Dim'"); - InstructionDesc[OpTypeTensorLayoutNV].operands.push(OperandId, "'ClampMode'"); - - InstructionDesc[OpTypeTensorViewNV].operands.push(OperandId, "'Dim'"); - InstructionDesc[OpTypeTensorViewNV].operands.push(OperandId, "'HasDimensions'"); - InstructionDesc[OpTypeTensorViewNV].operands.push(OperandVariableIds, "'p'"); - - InstructionDesc[OpTensorLayoutSetBlockSizeNV].operands.push(OperandId, "'TensorLayout'"); - InstructionDesc[OpTensorLayoutSetBlockSizeNV].operands.push(OperandVariableIds, "'BlockSize'"); - - InstructionDesc[OpTensorLayoutSetDimensionNV].operands.push(OperandId, "'TensorLayout'"); - InstructionDesc[OpTensorLayoutSetDimensionNV].operands.push(OperandVariableIds, "'Dim'"); - - InstructionDesc[OpTensorLayoutSetStrideNV].operands.push(OperandId, "'TensorLayout'"); - InstructionDesc[OpTensorLayoutSetStrideNV].operands.push(OperandVariableIds, "'Stride'"); - - InstructionDesc[OpTensorLayoutSliceNV].operands.push(OperandId, "'TensorLayout'"); - InstructionDesc[OpTensorLayoutSliceNV].operands.push(OperandVariableIds, "'Operands'"); - - InstructionDesc[OpTensorLayoutSetClampValueNV].operands.push(OperandId, "'TensorLayout'"); - InstructionDesc[OpTensorLayoutSetClampValueNV].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpTensorViewSetDimensionNV].operands.push(OperandId, "'TensorView'"); - InstructionDesc[OpTensorViewSetDimensionNV].operands.push(OperandVariableIds, "'Dim'"); - - InstructionDesc[OpTensorViewSetStrideNV].operands.push(OperandId, "'TensorView'"); - InstructionDesc[OpTensorViewSetStrideNV].operands.push(OperandVariableIds, "'Stride'"); - - InstructionDesc[OpTensorViewSetClipNV].operands.push(OperandId, "'TensorView'"); - InstructionDesc[OpTensorViewSetClipNV].operands.push(OperandId, "'ClipRowOffset'"); - InstructionDesc[OpTensorViewSetClipNV].operands.push(OperandId, "'ClipRowSpan'"); - InstructionDesc[OpTensorViewSetClipNV].operands.push(OperandId, "'ClipColOffset'"); - InstructionDesc[OpTensorViewSetClipNV].operands.push(OperandId, "'ClipColSpan'"); - }); -} - -} // end spv namespace diff --git a/include/SPIRV/doc.h b/include/SPIRV/doc.h deleted file mode 100644 index 8cd388a1..00000000 --- a/include/SPIRV/doc.h +++ /dev/null @@ -1,261 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Parameterize the SPIR-V enumerants. -// - -#pragma once - -#include "spirv.hpp" - -#include - -namespace spv { - -// Fill in all the parameters -void Parameterize(); - -// Return the English names of all the enums. -const char* SourceString(int); -const char* AddressingString(int); -const char* MemoryString(int); -const char* ExecutionModelString(int); -const char* ExecutionModeString(int); -const char* StorageClassString(int); -const char* DecorationString(int); -const char* BuiltInString(int); -const char* DimensionString(int); -const char* SelectControlString(int); -const char* LoopControlString(int); -const char* FunctionControlString(int); -const char* SamplerAddressingModeString(int); -const char* SamplerFilterModeString(int); -const char* ImageFormatString(int); -const char* ImageChannelOrderString(int); -const char* ImageChannelTypeString(int); -const char* ImageChannelDataTypeString(int type); -const char* ImageOperandsString(int format); -const char* ImageOperands(int); -const char* FPFastMathString(int); -const char* FPRoundingModeString(int); -const char* LinkageTypeString(int); -const char* FuncParamAttrString(int); -const char* AccessQualifierString(int); -const char* MemorySemanticsString(int); -const char* MemoryAccessString(int); -const char* ExecutionScopeString(int); -const char* GroupOperationString(int); -const char* KernelEnqueueFlagsString(int); -const char* KernelProfilingInfoString(int); -const char* CapabilityString(int); -const char* OpcodeString(int); -const char* ScopeString(int mem); - -// For grouping opcodes into subsections -enum OpcodeClass { - OpClassMisc, - OpClassDebug, - OpClassAnnotate, - OpClassExtension, - OpClassMode, - OpClassType, - OpClassConstant, - OpClassMemory, - OpClassFunction, - OpClassImage, - OpClassConvert, - OpClassComposite, - OpClassArithmetic, - OpClassBit, - OpClassRelationalLogical, - OpClassDerivative, - OpClassFlowControl, - OpClassAtomic, - OpClassPrimitive, - OpClassBarrier, - OpClassGroup, - OpClassDeviceSideEnqueue, - OpClassPipe, - - OpClassCount, - OpClassMissing // all instructions start out as missing -}; - -// For parameterizing operands. -enum OperandClass { - OperandNone, - OperandId, - OperandVariableIds, - OperandOptionalLiteral, - OperandOptionalLiteralString, - OperandVariableLiterals, - OperandVariableIdLiteral, - OperandVariableLiteralId, - OperandLiteralNumber, - OperandLiteralString, - OperandVariableLiteralStrings, - OperandSource, - OperandExecutionModel, - OperandAddressing, - OperandMemory, - OperandExecutionMode, - OperandStorage, - OperandDimensionality, - OperandSamplerAddressingMode, - OperandSamplerFilterMode, - OperandSamplerImageFormat, - OperandImageChannelOrder, - OperandImageChannelDataType, - OperandImageOperands, - OperandFPFastMath, - OperandFPRoundingMode, - OperandLinkageType, - OperandAccessQualifier, - OperandFuncParamAttr, - OperandDecoration, - OperandBuiltIn, - OperandSelect, - OperandLoop, - OperandFunction, - OperandMemorySemantics, - OperandMemoryAccess, - OperandScope, - OperandGroupOperation, - OperandKernelEnqueueFlags, - OperandKernelProfilingInfo, - OperandCapability, - OperandCooperativeMatrixOperands, - OperandTensorAddressingOperands, - - OperandOpcode, - - OperandCount -}; - -// Any specific enum can have a set of capabilities that allow it: -typedef std::vector EnumCaps; - -// Parameterize a set of operands with their OperandClass(es) and descriptions. -class OperandParameters { -public: - OperandParameters() { } - void push(OperandClass oc, const char* d, bool opt = false) - { - opClass.push_back(oc); - desc.push_back(d); - optional.push_back(opt); - } - void setOptional(); - OperandClass getClass(int op) const { return opClass[op]; } - const char* getDesc(int op) const { return desc[op]; } - bool isOptional(int op) const { return optional[op]; } - int getNum() const { return (int)opClass.size(); } - -protected: - std::vector opClass; - std::vector desc; - std::vector optional; -}; - -// Parameterize an enumerant -class EnumParameters { -public: - EnumParameters() : desc(nullptr) { } - const char* desc; -}; - -// Parameterize a set of enumerants that form an enum -class EnumDefinition : public EnumParameters { -public: - EnumDefinition() : - ceiling(0), bitmask(false), getName(nullptr), enumParams(nullptr), operandParams(nullptr) { } - void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) - { - ceiling = ceil; - getName = name; - bitmask = mask; - enumParams = ep; - } - void setOperands(OperandParameters* op) { operandParams = op; } - int ceiling; // ceiling of enumerants - bool bitmask; // true if these enumerants combine into a bitmask - const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) - EnumParameters* enumParams; // parameters for each individual enumerant - OperandParameters* operandParams; // sets of operands -}; - -// Parameterize an instruction's logical format, including its known set of operands, -// per OperandParameters above. -class InstructionParameters { -public: - InstructionParameters() : - opDesc("TBD"), - opClass(OpClassMissing), - typePresent(true), // most normal, only exceptions have to be spelled out - resultPresent(true) // most normal, only exceptions have to be spelled out - { } - - void setResultAndType(bool r, bool t) - { - resultPresent = r; - typePresent = t; - } - - bool hasResult() const { return resultPresent != 0; } - bool hasType() const { return typePresent != 0; } - - const char* opDesc; - OpcodeClass opClass; - OperandParameters operands; - -protected: - bool typePresent : 1; - bool resultPresent : 1; -}; - -// The set of objects that hold all the instruction/operand -// parameterization information. -extern InstructionParameters InstructionDesc[]; - -// These hold definitions of the enumerants used for operands -extern EnumDefinition OperandClassParams[]; - -const char* GetOperandDesc(OperandClass operand); -void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); -const char* AccessQualifierString(int attr); - -void PrintOperands(const OperandParameters& operands, int reservedOperands); - -} // end namespace spv diff --git a/include/SPIRV/hex_float.h b/include/SPIRV/hex_float.h deleted file mode 100644 index 785e8af1..00000000 --- a/include/SPIRV/hex_float.h +++ /dev/null @@ -1,1065 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ -#define LIBSPIRV_UTIL_HEX_FLOAT_H_ - -#include -#include -#include -#include -#include -#include -#include - -#include "bitutils.h" - -namespace spvutils { - -class Float16 { - public: - Float16(uint16_t v) : val(v) {} - Float16() {} - static bool isNan(const Float16& val) { - return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); - } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(const Float16& val) { - return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); - } - Float16(const Float16& other) { val = other.val; } - uint16_t get_value() const { return val; } - - // Returns the maximum normal value. - static Float16 max() { return Float16(0x7bff); } - // Returns the lowest normal value. - static Float16 lowest() { return Float16(0xfbff); } - - private: - uint16_t val; -}; - -// To specialize this type, you must override uint_type to define -// an unsigned integer that can fit your floating point type. -// You must also add a isNan function that returns true if -// a value is Nan. -template -struct FloatProxyTraits { - typedef void uint_type; -}; - -template <> -struct FloatProxyTraits { - typedef uint32_t uint_type; - static bool isNan(float f) { return std::isnan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(float f) { return std::isinf(f); } - // Returns the maximum normal value. - static float max() { return std::numeric_limits::max(); } - // Returns the lowest normal value. - static float lowest() { return std::numeric_limits::lowest(); } -}; - -template <> -struct FloatProxyTraits { - typedef uint64_t uint_type; - static bool isNan(double f) { return std::isnan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(double f) { return std::isinf(f); } - // Returns the maximum normal value. - static double max() { return std::numeric_limits::max(); } - // Returns the lowest normal value. - static double lowest() { return std::numeric_limits::lowest(); } -}; - -template <> -struct FloatProxyTraits { - typedef uint16_t uint_type; - static bool isNan(Float16 f) { return Float16::isNan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } - // Returns the maximum normal value. - static Float16 max() { return Float16::max(); } - // Returns the lowest normal value. - static Float16 lowest() { return Float16::lowest(); } -}; - -// Since copying a floating point number (especially if it is NaN) -// does not guarantee that bits are preserved, this class lets us -// store the type and use it as a float when necessary. -template -class FloatProxy { - public: - typedef typename FloatProxyTraits::uint_type uint_type; - - // Since this is to act similar to the normal floats, - // do not initialize the data by default. - FloatProxy() {} - - // Intentionally non-explicit. This is a proxy type so - // implicit conversions allow us to use it more transparently. - FloatProxy(T val) { data_ = BitwiseCast(val); } - - // Intentionally non-explicit. This is a proxy type so - // implicit conversions allow us to use it more transparently. - FloatProxy(uint_type val) { data_ = val; } - - // This is helpful to have and is guaranteed not to stomp bits. - FloatProxy operator-() const { - return static_cast(data_ ^ - (uint_type(0x1) << (sizeof(T) * 8 - 1))); - } - - // Returns the data as a floating point value. - T getAsFloat() const { return BitwiseCast(data_); } - - // Returns the raw data. - uint_type data() const { return data_; } - - // Returns true if the value represents any type of NaN. - bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } - // Returns true if the value represents any type of infinity. - bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } - - // Returns the maximum normal value. - static FloatProxy max() { - return FloatProxy(FloatProxyTraits::max()); - } - // Returns the lowest normal value. - static FloatProxy lowest() { - return FloatProxy(FloatProxyTraits::lowest()); - } - - private: - uint_type data_; -}; - -template -bool operator==(const FloatProxy& first, const FloatProxy& second) { - return first.data() == second.data(); -} - -// Reads a FloatProxy value as a normal float from a stream. -template -std::istream& operator>>(std::istream& is, FloatProxy& value) { - T float_val; - is >> float_val; - value = FloatProxy(float_val); - return is; -} - -// This is an example traits. It is not meant to be used in practice, but will -// be the default for any non-specialized type. -template -struct HexFloatTraits { - // Integer type that can store this hex-float. - typedef void uint_type; - // Signed integer type that can store this hex-float. - typedef void int_type; - // The numerical type that this HexFloat represents. - typedef void underlying_type; - // The type needed to construct the underlying type. - typedef void native_type; - // The number of bits that are actually relevant in the uint_type. - // This allows us to deal with, for example, 24-bit values in a 32-bit - // integer. - static const uint32_t num_used_bits = 0; - // Number of bits that represent the exponent. - static const uint32_t num_exponent_bits = 0; - // Number of bits that represent the fractional part. - static const uint32_t num_fraction_bits = 0; - // The bias of the exponent. (How much we need to subtract from the stored - // value to get the correct value.) - static const uint32_t exponent_bias = 0; -}; - -// Traits for IEEE float. -// 1 sign bit, 8 exponent bits, 23 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint32_t uint_type; - typedef int32_t int_type; - typedef FloatProxy underlying_type; - typedef float native_type; - static const uint_type num_used_bits = 32; - static const uint_type num_exponent_bits = 8; - static const uint_type num_fraction_bits = 23; - static const uint_type exponent_bias = 127; -}; - -// Traits for IEEE double. -// 1 sign bit, 11 exponent bits, 52 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint64_t uint_type; - typedef int64_t int_type; - typedef FloatProxy underlying_type; - typedef double native_type; - static const uint_type num_used_bits = 64; - static const uint_type num_exponent_bits = 11; - static const uint_type num_fraction_bits = 52; - static const uint_type exponent_bias = 1023; -}; - -// Traits for IEEE half. -// 1 sign bit, 5 exponent bits, 10 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint16_t uint_type; - typedef int16_t int_type; - typedef uint16_t underlying_type; - typedef uint16_t native_type; - static const uint_type num_used_bits = 16; - static const uint_type num_exponent_bits = 5; - static const uint_type num_fraction_bits = 10; - static const uint_type exponent_bias = 15; -}; - -enum round_direction { - kRoundToZero, - kRoundToNearestEven, - kRoundToPositiveInfinity, - kRoundToNegativeInfinity -}; - -// Template class that houses a floating pointer number. -// It exposes a number of constants based on the provided traits to -// assist in interpreting the bits of the value. -template > -class HexFloat { - public: - typedef typename Traits::uint_type uint_type; - typedef typename Traits::int_type int_type; - typedef typename Traits::underlying_type underlying_type; - typedef typename Traits::native_type native_type; - - explicit HexFloat(T f) : value_(f) {} - - T value() const { return value_; } - void set_value(T f) { value_ = f; } - - // These are all written like this because it is convenient to have - // compile-time constants for all of these values. - - // Pass-through values to save typing. - static const uint32_t num_used_bits = Traits::num_used_bits; - static const uint32_t exponent_bias = Traits::exponent_bias; - static const uint32_t num_exponent_bits = Traits::num_exponent_bits; - static const uint32_t num_fraction_bits = Traits::num_fraction_bits; - - // Number of bits to shift left to set the highest relevant bit. - static const uint32_t top_bit_left_shift = num_used_bits - 1; - // How many nibbles (hex characters) the fractional part takes up. - static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; - // If the fractional part does not fit evenly into a hex character (4-bits) - // then we have to left-shift to get rid of leading 0s. This is the amount - // we have to shift (might be 0). - static const uint32_t num_overflow_bits = - fraction_nibbles * 4 - num_fraction_bits; - - // The representation of the fraction, not the actual bits. This - // includes the leading bit that is usually implicit. - static const uint_type fraction_represent_mask = - spvutils::SetBits::get; - - // The topmost bit in the nibble-aligned fraction. - static const uint_type fraction_top_bit = - uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); - - // The least significant bit in the exponent, which is also the bit - // immediately to the left of the significand. - static const uint_type first_exponent_bit = uint_type(1) - << (num_fraction_bits); - - // The mask for the encoded fraction. It does not include the - // implicit bit. - static const uint_type fraction_encode_mask = - spvutils::SetBits::get; - - // The bit that is used as a sign. - static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; - - // The bits that represent the exponent. - static const uint_type exponent_mask = - spvutils::SetBits::get; - - // How far left the exponent is shifted. - static const uint32_t exponent_left_shift = num_fraction_bits; - - // How far from the right edge the fraction is shifted. - static const uint32_t fraction_right_shift = - static_cast(sizeof(uint_type) * 8) - num_fraction_bits; - - // The maximum representable unbiased exponent. - static const int_type max_exponent = - (exponent_mask >> num_fraction_bits) - exponent_bias; - // The minimum representable exponent for normalized numbers. - static const int_type min_exponent = -static_cast(exponent_bias); - - // Returns the bits associated with the value. - uint_type getBits() const { return spvutils::BitwiseCast(value_); } - - // Returns the bits associated with the value, without the leading sign bit. - uint_type getUnsignedBits() const { - return static_cast(spvutils::BitwiseCast(value_) & - ~sign_mask); - } - - // Returns the bits associated with the exponent, shifted to start at the - // lsb of the type. - const uint_type getExponentBits() const { - return static_cast((getBits() & exponent_mask) >> - num_fraction_bits); - } - - // Returns the exponent in unbiased form. This is the exponent in the - // human-friendly form. - const int_type getUnbiasedExponent() const { - return static_cast(getExponentBits() - exponent_bias); - } - - // Returns just the significand bits from the value. - const uint_type getSignificandBits() const { - return getBits() & fraction_encode_mask; - } - - // If the number was normalized, returns the unbiased exponent. - // If the number was denormal, normalize the exponent first. - const int_type getUnbiasedNormalizedExponent() const { - if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 - return 0; - } - int_type exp = getUnbiasedExponent(); - if (exp == min_exponent) { // We are in denorm land. - uint_type significand_bits = getSignificandBits(); - while ((significand_bits & (first_exponent_bit >> 1)) == 0) { - significand_bits = static_cast(significand_bits << 1); - exp = static_cast(exp - 1); - } - significand_bits &= fraction_encode_mask; - } - return exp; - } - - // Returns the signficand after it has been normalized. - const uint_type getNormalizedSignificand() const { - int_type unbiased_exponent = getUnbiasedNormalizedExponent(); - uint_type significand = getSignificandBits(); - for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { - significand = static_cast(significand << 1); - } - significand &= fraction_encode_mask; - return significand; - } - - // Returns true if this number represents a negative value. - bool isNegative() const { return (getBits() & sign_mask) != 0; } - - // Sets this HexFloat from the individual components. - // Note this assumes EVERY significand is normalized, and has an implicit - // leading one. This means that the only way that this method will set 0, - // is if you set a number so denormalized that it underflows. - // Do not use this method with raw bits extracted from a subnormal number, - // since subnormals do not have an implicit leading 1 in the significand. - // The significand is also expected to be in the - // lowest-most num_fraction_bits of the uint_type. - // The exponent is expected to be unbiased, meaning an exponent of - // 0 actually means 0. - // If underflow_round_up is set, then on underflow, if a number is non-0 - // and would underflow, we round up to the smallest denorm. - void setFromSignUnbiasedExponentAndNormalizedSignificand( - bool negative, int_type exponent, uint_type significand, - bool round_denorm_up) { - bool significand_is_zero = significand == 0; - - if (exponent <= min_exponent) { - // If this was denormalized, then we have to shift the bit on, meaning - // the significand is not zero. - significand_is_zero = false; - significand |= first_exponent_bit; - significand = static_cast(significand >> 1); - } - - while (exponent < min_exponent) { - significand = static_cast(significand >> 1); - ++exponent; - } - - if (exponent == min_exponent) { - if (significand == 0 && !significand_is_zero && round_denorm_up) { - significand = static_cast(0x1); - } - } - - uint_type new_value = 0; - if (negative) { - new_value = static_cast(new_value | sign_mask); - } - exponent = static_cast(exponent + exponent_bias); - assert(exponent >= 0); - - // put it all together - exponent = static_cast((exponent << exponent_left_shift) & - exponent_mask); - significand = static_cast(significand & fraction_encode_mask); - new_value = static_cast(new_value | (exponent | significand)); - value_ = BitwiseCast(new_value); - } - - // Increments the significand of this number by the given amount. - // If this would spill the significand into the implicit bit, - // carry is set to true and the significand is shifted to fit into - // the correct location, otherwise carry is set to false. - // All significands and to_increment are assumed to be within the bounds - // for a valid significand. - static uint_type incrementSignificand(uint_type significand, - uint_type to_increment, bool* carry) { - significand = static_cast(significand + to_increment); - *carry = false; - if (significand & first_exponent_bit) { - *carry = true; - // The implicit 1-bit will have carried, so we should zero-out the - // top bit and shift back. - significand = static_cast(significand & ~first_exponent_bit); - significand = static_cast(significand >> 1); - } - return significand; - } - - // These exist because MSVC throws warnings on negative right-shifts - // even if they are not going to be executed. Eg: - // constant_number < 0? 0: constant_number - // These convert the negative left-shifts into right shifts. - - template - uint_type negatable_left_shift(int_type N, uint_type val) - { - if(N >= 0) - return val << N; - - return val >> -N; - } - - template - uint_type negatable_right_shift(int_type N, uint_type val) - { - if(N >= 0) - return val >> N; - - return val << -N; - } - - // Returns the significand, rounded to fit in a significand in - // other_T. This is shifted so that the most significant - // bit of the rounded number lines up with the most significant bit - // of the returned significand. - template - typename other_T::uint_type getRoundedNormalizedSignificand( - round_direction dir, bool* carry_bit) { - typedef typename other_T::uint_type other_uint_type; - static const int_type num_throwaway_bits = - static_cast(num_fraction_bits) - - static_cast(other_T::num_fraction_bits); - - static const uint_type last_significant_bit = - (num_throwaway_bits < 0) - ? 0 - : negatable_left_shift(num_throwaway_bits, 1u); - static const uint_type first_rounded_bit = - (num_throwaway_bits < 1) - ? 0 - : negatable_left_shift(num_throwaway_bits - 1, 1u); - - static const uint_type throwaway_mask_bits = - num_throwaway_bits > 0 ? num_throwaway_bits : 0; - static const uint_type throwaway_mask = - spvutils::SetBits::get; - - *carry_bit = false; - other_uint_type out_val = 0; - uint_type significand = getNormalizedSignificand(); - // If we are up-casting, then we just have to shift to the right location. - if (num_throwaway_bits <= 0) { - out_val = static_cast(significand); - uint_type shift_amount = static_cast(-num_throwaway_bits); - out_val = static_cast(out_val << shift_amount); - return out_val; - } - - // If every non-representable bit is 0, then we don't have any casting to - // do. - if ((significand & throwaway_mask) == 0) { - return static_cast( - negatable_right_shift(num_throwaway_bits, significand)); - } - - bool round_away_from_zero = false; - // We actually have to narrow the significand here, so we have to follow the - // rounding rules. - switch (dir) { - case kRoundToZero: - break; - case kRoundToPositiveInfinity: - round_away_from_zero = !isNegative(); - break; - case kRoundToNegativeInfinity: - round_away_from_zero = isNegative(); - break; - case kRoundToNearestEven: - // Have to round down, round bit is 0 - if ((first_rounded_bit & significand) == 0) { - break; - } - if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { - // If any subsequent bit of the rounded portion is non-0 then we round - // up. - round_away_from_zero = true; - break; - } - // We are exactly half-way between 2 numbers, pick even. - if ((significand & last_significant_bit) != 0) { - // 1 for our last bit, round up. - round_away_from_zero = true; - break; - } - break; - } - - if (round_away_from_zero) { - return static_cast( - negatable_right_shift(num_throwaway_bits, incrementSignificand( - significand, last_significant_bit, carry_bit))); - } else { - return static_cast( - negatable_right_shift(num_throwaway_bits, significand)); - } - } - - // Casts this value to another HexFloat. If the cast is widening, - // then round_dir is ignored. If the cast is narrowing, then - // the result is rounded in the direction specified. - // This number will retain Nan and Inf values. - // It will also saturate to Inf if the number overflows, and - // underflow to (0 or min depending on rounding) if the number underflows. - template - void castTo(other_T& other, round_direction round_dir) { - other = other_T(static_cast(0)); - bool negate = isNegative(); - if (getUnsignedBits() == 0) { - if (negate) { - other.set_value(-other.value()); - } - return; - } - uint_type significand = getSignificandBits(); - bool carried = false; - typename other_T::uint_type rounded_significand = - getRoundedNormalizedSignificand(round_dir, &carried); - - int_type exponent = getUnbiasedExponent(); - if (exponent == min_exponent) { - // If we are denormal, normalize the exponent, so that we can encode - // easily. - exponent = static_cast(exponent + 1); - for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; - check_bit = static_cast(check_bit >> 1)) { - exponent = static_cast(exponent - 1); - if (check_bit & significand) break; - } - } - - bool is_nan = - (getBits() & exponent_mask) == exponent_mask && significand != 0; - bool is_inf = - !is_nan && - ((exponent + carried) > static_cast(other_T::exponent_bias) || - (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); - - // If we are Nan or Inf we should pass that through. - if (is_inf) { - other.set_value(BitwiseCast( - static_cast( - (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); - return; - } - if (is_nan) { - typename other_T::uint_type shifted_significand; - shifted_significand = static_cast( - negatable_left_shift( - static_cast(other_T::num_fraction_bits) - - static_cast(num_fraction_bits), significand)); - - // We are some sort of Nan. We try to keep the bit-pattern of the Nan - // as close as possible. If we had to shift off bits so we are 0, then we - // just set the last bit. - other.set_value(BitwiseCast( - static_cast( - (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | - (shifted_significand == 0 ? 0x1 : shifted_significand)))); - return; - } - - bool round_underflow_up = - isNegative() ? round_dir == kRoundToNegativeInfinity - : round_dir == kRoundToPositiveInfinity; - typedef typename other_T::int_type other_int_type; - // setFromSignUnbiasedExponentAndNormalizedSignificand will - // zero out any underflowing value (but retain the sign). - other.setFromSignUnbiasedExponentAndNormalizedSignificand( - negate, static_cast(exponent), rounded_significand, - round_underflow_up); - return; - } - - private: - T value_; - - static_assert(num_used_bits == - Traits::num_exponent_bits + Traits::num_fraction_bits + 1, - "The number of bits do not fit"); - static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); -}; - -// Returns 4 bits represented by the hex character. -inline uint8_t get_nibble_from_character(int character) { - const char* dec = "0123456789"; - const char* lower = "abcdef"; - const char* upper = "ABCDEF"; - const char* p = nullptr; - if ((p = strchr(dec, character))) { - return static_cast(p - dec); - } else if ((p = strchr(lower, character))) { - return static_cast(p - lower + 0xa); - } else if ((p = strchr(upper, character))) { - return static_cast(p - upper + 0xa); - } - - assert(false && "This was called with a non-hex character"); - return 0; -} - -// Outputs the given HexFloat to the stream. -template -std::ostream& operator<<(std::ostream& os, const HexFloat& value) { - typedef HexFloat HF; - typedef typename HF::uint_type uint_type; - typedef typename HF::int_type int_type; - - static_assert(HF::num_used_bits != 0, - "num_used_bits must be non-zero for a valid float"); - static_assert(HF::num_exponent_bits != 0, - "num_exponent_bits must be non-zero for a valid float"); - static_assert(HF::num_fraction_bits != 0, - "num_fractin_bits must be non-zero for a valid float"); - - const uint_type bits = spvutils::BitwiseCast(value.value()); - const char* const sign = (bits & HF::sign_mask) ? "-" : ""; - const uint_type exponent = static_cast( - (bits & HF::exponent_mask) >> HF::num_fraction_bits); - - uint_type fraction = static_cast((bits & HF::fraction_encode_mask) - << HF::num_overflow_bits); - - const bool is_zero = exponent == 0 && fraction == 0; - const bool is_denorm = exponent == 0 && !is_zero; - - // exponent contains the biased exponent we have to convert it back into - // the normal range. - int_type int_exponent = static_cast(exponent - HF::exponent_bias); - // If the number is all zeros, then we actually have to NOT shift the - // exponent. - int_exponent = is_zero ? 0 : int_exponent; - - // If we are denorm, then start shifting, and decreasing the exponent until - // our leading bit is 1. - - if (is_denorm) { - while ((fraction & HF::fraction_top_bit) == 0) { - fraction = static_cast(fraction << 1); - int_exponent = static_cast(int_exponent - 1); - } - // Since this is denormalized, we have to consume the leading 1 since it - // will end up being implicit. - fraction = static_cast(fraction << 1); // eat the leading 1 - fraction &= HF::fraction_represent_mask; - } - - uint_type fraction_nibbles = HF::fraction_nibbles; - // We do not have to display any trailing 0s, since this represents the - // fractional part. - while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { - // Shift off any trailing values; - fraction = static_cast(fraction >> 4); - --fraction_nibbles; - } - - const auto saved_flags = os.flags(); - const auto saved_fill = os.fill(); - - os << sign << "0x" << (is_zero ? '0' : '1'); - if (fraction_nibbles) { - // Make sure to keep the leading 0s in place, since this is the fractional - // part. - os << "." << std::setw(static_cast(fraction_nibbles)) - << std::setfill('0') << std::hex << fraction; - } - os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; - - os.flags(saved_flags); - os.fill(saved_fill); - - return os; -} - -// Returns true if negate_value is true and the next character on the -// input stream is a plus or minus sign. In that case we also set the fail bit -// on the stream and set the value to the zero value for its type. -template -inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, - HexFloat& value) { - if (negate_value) { - auto next_char = is.peek(); - if (next_char == '-' || next_char == '+') { - // Fail the parse. Emulate standard behaviour by setting the value to - // the zero value, and set the fail bit on the stream. - value = HexFloat(typename HexFloat::uint_type(0)); - is.setstate(std::ios_base::failbit); - return true; - } - } - return false; -} - -// Parses a floating point number from the given stream and stores it into the -// value parameter. -// If negate_value is true then the number may not have a leading minus or -// plus, and if it successfully parses, then the number is negated before -// being stored into the value parameter. -// If the value cannot be correctly parsed or overflows the target floating -// point type, then set the fail bit on the stream. -// TODO(dneto): Promise C++11 standard behavior in how the value is set in -// the error case, but only after all target platforms implement it correctly. -// In particular, the Microsoft C++ runtime appears to be out of spec. -template -inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, - HexFloat& value) { - if (RejectParseDueToLeadingSign(is, negate_value, value)) { - return is; - } - T val; - is >> val; - if (negate_value) { - val = -val; - } - value.set_value(val); - // In the failure case, map -0.0 to 0.0. - if (is.fail() && value.getUnsignedBits() == 0u) { - value = HexFloat(typename HexFloat::uint_type(0)); - } - if (val.isInfinity()) { - // Fail the parse. Emulate standard behaviour by setting the value to - // the closest normal value, and set the fail bit on the stream. - value.set_value((value.isNegative() || negate_value) ? T::lowest() - : T::max()); - is.setstate(std::ios_base::failbit); - } - return is; -} - -// Specialization of ParseNormalFloat for FloatProxy values. -// This will parse the float as it were a 32-bit floating point number, -// and then round it down to fit into a Float16 value. -// The number is rounded towards zero. -// If negate_value is true then the number may not have a leading minus or -// plus, and if it successfully parses, then the number is negated before -// being stored into the value parameter. -// If the value cannot be correctly parsed or overflows the target floating -// point type, then set the fail bit on the stream. -// TODO(dneto): Promise C++11 standard behavior in how the value is set in -// the error case, but only after all target platforms implement it correctly. -// In particular, the Microsoft C++ runtime appears to be out of spec. -template <> -inline std::istream& -ParseNormalFloat, HexFloatTraits>>( - std::istream& is, bool negate_value, - HexFloat, HexFloatTraits>>& value) { - // First parse as a 32-bit float. - HexFloat> float_val(0.0f); - ParseNormalFloat(is, negate_value, float_val); - - // Then convert to 16-bit float, saturating at infinities, and - // rounding toward zero. - float_val.castTo(value, kRoundToZero); - - // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the - // fail bit and set the lowest or highest value. - if (Float16::isInfinity(value.value().getAsFloat())) { - value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); - is.setstate(std::ios_base::failbit); - } - return is; -} - -// Reads a HexFloat from the given stream. -// If the float is not encoded as a hex-float then it will be parsed -// as a regular float. -// This may fail if your stream does not support at least one unget. -// Nan values can be encoded with "0x1.p+exponent_bias". -// This would normally overflow a float and round to -// infinity but this special pattern is the exact representation for a NaN, -// and therefore is actually encoded as the correct NaN. To encode inf, -// either 0x0p+exponent_bias can be specified or any exponent greater than -// exponent_bias. -// Examples using IEEE 32-bit float encoding. -// 0x1.0p+128 (+inf) -// -0x1.0p-128 (-inf) -// -// 0x1.1p+128 (+Nan) -// -0x1.1p+128 (-Nan) -// -// 0x1p+129 (+inf) -// -0x1p+129 (-inf) -template -std::istream& operator>>(std::istream& is, HexFloat& value) { - using HF = HexFloat; - using uint_type = typename HF::uint_type; - using int_type = typename HF::int_type; - - value.set_value(static_cast(0.f)); - - if (is.flags() & std::ios::skipws) { - // If the user wants to skip whitespace , then we should obey that. - while (std::isspace(is.peek())) { - is.get(); - } - } - - auto next_char = is.peek(); - bool negate_value = false; - - if (next_char != '-' && next_char != '0') { - return ParseNormalFloat(is, negate_value, value); - } - - if (next_char == '-') { - negate_value = true; - is.get(); - next_char = is.peek(); - } - - if (next_char == '0') { - is.get(); // We may have to unget this. - auto maybe_hex_start = is.peek(); - if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { - is.unget(); - return ParseNormalFloat(is, negate_value, value); - } else { - is.get(); // Throw away the 'x'; - } - } else { - return ParseNormalFloat(is, negate_value, value); - } - - // This "looks" like a hex-float so treat it as one. - bool seen_p = false; - bool seen_dot = false; - uint_type fraction_index = 0; - - uint_type fraction = 0; - int_type exponent = HF::exponent_bias; - - // Strip off leading zeros so we don't have to special-case them later. - while ((next_char = is.peek()) == '0') { - is.get(); - } - - bool is_denorm = - true; // Assume denorm "representation" until we hear otherwise. - // NB: This does not mean the value is actually denorm, - // it just means that it was written 0. - bool bits_written = false; // Stays false until we write a bit. - while (!seen_p && !seen_dot) { - // Handle characters that are left of the fractional part. - if (next_char == '.') { - seen_dot = true; - } else if (next_char == 'p') { - seen_p = true; - } else if (::isxdigit(next_char)) { - // We know this is not denormalized since we have stripped all leading - // zeroes and we are not a ".". - is_denorm = false; - int number = get_nibble_from_character(next_char); - for (int i = 0; i < 4; ++i, number <<= 1) { - uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; - if (bits_written) { - // If we are here the bits represented belong in the fractional - // part of the float, and we have to adjust the exponent accordingly. - fraction = static_cast( - fraction | - static_cast( - write_bit << (HF::top_bit_left_shift - fraction_index++))); - exponent = static_cast(exponent + 1); - } - bits_written |= write_bit != 0; - } - } else { - // We have not found our exponent yet, so we have to fail. - is.setstate(std::ios::failbit); - return is; - } - is.get(); - next_char = is.peek(); - } - bits_written = false; - while (seen_dot && !seen_p) { - // Handle only fractional parts now. - if (next_char == 'p') { - seen_p = true; - } else if (::isxdigit(next_char)) { - int number = get_nibble_from_character(next_char); - for (int i = 0; i < 4; ++i, number <<= 1) { - uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; - bits_written |= write_bit != 0; - if (is_denorm && !bits_written) { - // Handle modifying the exponent here this way we can handle - // an arbitrary number of hex values without overflowing our - // integer. - exponent = static_cast(exponent - 1); - } else { - fraction = static_cast( - fraction | - static_cast( - write_bit << (HF::top_bit_left_shift - fraction_index++))); - } - } - } else { - // We still have not found our 'p' exponent yet, so this is not a valid - // hex-float. - is.setstate(std::ios::failbit); - return is; - } - is.get(); - next_char = is.peek(); - } - - bool seen_sign = false; - int8_t exponent_sign = 1; - int_type written_exponent = 0; - while (true) { - if ((next_char == '-' || next_char == '+')) { - if (seen_sign) { - is.setstate(std::ios::failbit); - return is; - } - seen_sign = true; - exponent_sign = (next_char == '-') ? -1 : 1; - } else if (::isdigit(next_char)) { - // Hex-floats express their exponent as decimal. - written_exponent = static_cast(written_exponent * 10); - written_exponent = - static_cast(written_exponent + (next_char - '0')); - } else { - break; - } - is.get(); - next_char = is.peek(); - } - - written_exponent = static_cast(written_exponent * exponent_sign); - exponent = static_cast(exponent + written_exponent); - - bool is_zero = is_denorm && (fraction == 0); - if (is_denorm && !is_zero) { - fraction = static_cast(fraction << 1); - exponent = static_cast(exponent - 1); - } else if (is_zero) { - exponent = 0; - } - - if (exponent <= 0 && !is_zero) { - fraction = static_cast(fraction >> 1); - fraction |= static_cast(1) << HF::top_bit_left_shift; - } - - fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; - - const int_type max_exponent = - SetBits::get; - - // Handle actual denorm numbers - while (exponent < 0 && !is_zero) { - fraction = static_cast(fraction >> 1); - exponent = static_cast(exponent + 1); - - fraction &= HF::fraction_encode_mask; - if (fraction == 0) { - // We have underflowed our fraction. We should clamp to zero. - is_zero = true; - exponent = 0; - } - } - - // We have overflowed so we should be inf/-inf. - if (exponent > max_exponent) { - exponent = max_exponent; - fraction = 0; - } - - uint_type output_bits = static_cast( - static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); - output_bits |= fraction; - - uint_type shifted_exponent = static_cast( - static_cast(exponent << HF::exponent_left_shift) & - HF::exponent_mask); - output_bits |= shifted_exponent; - - T output_float = spvutils::BitwiseCast(output_bits); - value.set_value(output_float); - - return is; -} - -// Writes a FloatProxy value to a stream. -// Zero and normal numbers are printed in the usual notation, but with -// enough digits to fully reproduce the value. Other values (subnormal, -// NaN, and infinity) are printed as a hex float. -template -std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { - auto float_val = value.getAsFloat(); - switch (std::fpclassify(float_val)) { - case FP_ZERO: - case FP_NORMAL: { - auto saved_precision = os.precision(); - os.precision(std::numeric_limits::digits10); - os << float_val; - os.precision(saved_precision); - } break; - default: - os << HexFloat>(value); - break; - } - return os; -} - -template <> -inline std::ostream& operator<<(std::ostream& os, - const FloatProxy& value) { - os << HexFloat>(value); - return os; -} -} - -#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/include/SPIRV/spirv.hpp b/include/SPIRV/spirv.hpp deleted file mode 100644 index 0f28bb51..00000000 --- a/include/SPIRV/spirv.hpp +++ /dev/null @@ -1,4936 +0,0 @@ -// Copyright (c) 2014-2024 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and/or associated documentation files (the "Materials"), -// to deal in the Materials without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Materials, and to permit persons to whom the -// Materials are furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -// IN THE MATERIALS. - -// This header is automatically generated by the same tool that creates -// the Binary Section of the SPIR-V specification. - -// Enumeration tokens for SPIR-V, in various styles: -// C, C++, C++11, JSON, Lua, Python, C#, D, Beef -// -// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL -// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL -// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL -// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL -// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -// - C# will use enum classes in the Specification class located in the "Spv" namespace, -// e.g.: Spv.Specification.SourceLanguage.GLSL -// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL -// - Beef will use enum classes in the Specification class located in the "Spv" namespace, -// e.g.: Spv.Specification.SourceLanguage.GLSL -// -// Some tokens act like mask values, which can be OR'd together, -// while others are mutually exclusive. The mask-like ones have -// "Mask" in their name, and a parallel enum that has the shift -// amount (1 << x) for each corresponding enumerant. - -#ifndef spirv_HPP -#define spirv_HPP - -namespace spv { - -typedef unsigned int Id; - -#define SPV_VERSION 0x10600 -#define SPV_REVISION 1 - -static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010600; -static const unsigned int Revision = 1; -static const unsigned int OpCodeMask = 0xffff; -static const unsigned int WordCountShift = 16; - -enum SourceLanguage { - SourceLanguageUnknown = 0, - SourceLanguageESSL = 1, - SourceLanguageGLSL = 2, - SourceLanguageOpenCL_C = 3, - SourceLanguageOpenCL_CPP = 4, - SourceLanguageHLSL = 5, - SourceLanguageCPP_for_OpenCL = 6, - SourceLanguageSYCL = 7, - SourceLanguageHERO_C = 8, - SourceLanguageNZSL = 9, - SourceLanguageWGSL = 10, - SourceLanguageSlang = 11, - SourceLanguageZig = 12, - SourceLanguageMax = 0x7fffffff, -}; - -enum ExecutionModel { - ExecutionModelVertex = 0, - ExecutionModelTessellationControl = 1, - ExecutionModelTessellationEvaluation = 2, - ExecutionModelGeometry = 3, - ExecutionModelFragment = 4, - ExecutionModelGLCompute = 5, - ExecutionModelKernel = 6, - ExecutionModelTaskNV = 5267, - ExecutionModelMeshNV = 5268, - ExecutionModelRayGenerationKHR = 5313, - ExecutionModelRayGenerationNV = 5313, - ExecutionModelIntersectionKHR = 5314, - ExecutionModelIntersectionNV = 5314, - ExecutionModelAnyHitKHR = 5315, - ExecutionModelAnyHitNV = 5315, - ExecutionModelClosestHitKHR = 5316, - ExecutionModelClosestHitNV = 5316, - ExecutionModelMissKHR = 5317, - ExecutionModelMissNV = 5317, - ExecutionModelCallableKHR = 5318, - ExecutionModelCallableNV = 5318, - ExecutionModelTaskEXT = 5364, - ExecutionModelMeshEXT = 5365, - ExecutionModelMax = 0x7fffffff, -}; - -enum AddressingModel { - AddressingModelLogical = 0, - AddressingModelPhysical32 = 1, - AddressingModelPhysical64 = 2, - AddressingModelPhysicalStorageBuffer64 = 5348, - AddressingModelPhysicalStorageBuffer64EXT = 5348, - AddressingModelMax = 0x7fffffff, -}; - -enum MemoryModel { - MemoryModelSimple = 0, - MemoryModelGLSL450 = 1, - MemoryModelOpenCL = 2, - MemoryModelVulkan = 3, - MemoryModelVulkanKHR = 3, - MemoryModelMax = 0x7fffffff, -}; - -enum ExecutionMode { - ExecutionModeInvocations = 0, - ExecutionModeSpacingEqual = 1, - ExecutionModeSpacingFractionalEven = 2, - ExecutionModeSpacingFractionalOdd = 3, - ExecutionModeVertexOrderCw = 4, - ExecutionModeVertexOrderCcw = 5, - ExecutionModePixelCenterInteger = 6, - ExecutionModeOriginUpperLeft = 7, - ExecutionModeOriginLowerLeft = 8, - ExecutionModeEarlyFragmentTests = 9, - ExecutionModePointMode = 10, - ExecutionModeXfb = 11, - ExecutionModeDepthReplacing = 12, - ExecutionModeDepthGreater = 14, - ExecutionModeDepthLess = 15, - ExecutionModeDepthUnchanged = 16, - ExecutionModeLocalSize = 17, - ExecutionModeLocalSizeHint = 18, - ExecutionModeInputPoints = 19, - ExecutionModeInputLines = 20, - ExecutionModeInputLinesAdjacency = 21, - ExecutionModeTriangles = 22, - ExecutionModeInputTrianglesAdjacency = 23, - ExecutionModeQuads = 24, - ExecutionModeIsolines = 25, - ExecutionModeOutputVertices = 26, - ExecutionModeOutputPoints = 27, - ExecutionModeOutputLineStrip = 28, - ExecutionModeOutputTriangleStrip = 29, - ExecutionModeVecTypeHint = 30, - ExecutionModeContractionOff = 31, - ExecutionModeInitializer = 33, - ExecutionModeFinalizer = 34, - ExecutionModeSubgroupSize = 35, - ExecutionModeSubgroupsPerWorkgroup = 36, - ExecutionModeSubgroupsPerWorkgroupId = 37, - ExecutionModeLocalSizeId = 38, - ExecutionModeLocalSizeHintId = 39, - ExecutionModeNonCoherentColorAttachmentReadEXT = 4169, - ExecutionModeNonCoherentDepthAttachmentReadEXT = 4170, - ExecutionModeNonCoherentStencilAttachmentReadEXT = 4171, - ExecutionModeSubgroupUniformControlFlowKHR = 4421, - ExecutionModePostDepthCoverage = 4446, - ExecutionModeDenormPreserve = 4459, - ExecutionModeDenormFlushToZero = 4460, - ExecutionModeSignedZeroInfNanPreserve = 4461, - ExecutionModeRoundingModeRTE = 4462, - ExecutionModeRoundingModeRTZ = 4463, - ExecutionModeEarlyAndLateFragmentTestsAMD = 5017, - ExecutionModeStencilRefReplacingEXT = 5027, - ExecutionModeCoalescingAMDX = 5069, - ExecutionModeIsApiEntryAMDX = 5070, - ExecutionModeMaxNodeRecursionAMDX = 5071, - ExecutionModeStaticNumWorkgroupsAMDX = 5072, - ExecutionModeShaderIndexAMDX = 5073, - ExecutionModeMaxNumWorkgroupsAMDX = 5077, - ExecutionModeStencilRefUnchangedFrontAMD = 5079, - ExecutionModeStencilRefGreaterFrontAMD = 5080, - ExecutionModeStencilRefLessFrontAMD = 5081, - ExecutionModeStencilRefUnchangedBackAMD = 5082, - ExecutionModeStencilRefGreaterBackAMD = 5083, - ExecutionModeStencilRefLessBackAMD = 5084, - ExecutionModeQuadDerivativesKHR = 5088, - ExecutionModeRequireFullQuadsKHR = 5089, - ExecutionModeSharesInputWithAMDX = 5102, - ExecutionModeOutputLinesEXT = 5269, - ExecutionModeOutputLinesNV = 5269, - ExecutionModeOutputPrimitivesEXT = 5270, - ExecutionModeOutputPrimitivesNV = 5270, - ExecutionModeDerivativeGroupQuadsKHR = 5289, - ExecutionModeDerivativeGroupQuadsNV = 5289, - ExecutionModeDerivativeGroupLinearKHR = 5290, - ExecutionModeDerivativeGroupLinearNV = 5290, - ExecutionModeOutputTrianglesEXT = 5298, - ExecutionModeOutputTrianglesNV = 5298, - ExecutionModePixelInterlockOrderedEXT = 5366, - ExecutionModePixelInterlockUnorderedEXT = 5367, - ExecutionModeSampleInterlockOrderedEXT = 5368, - ExecutionModeSampleInterlockUnorderedEXT = 5369, - ExecutionModeShadingRateInterlockOrderedEXT = 5370, - ExecutionModeShadingRateInterlockUnorderedEXT = 5371, - ExecutionModeSharedLocalMemorySizeINTEL = 5618, - ExecutionModeRoundingModeRTPINTEL = 5620, - ExecutionModeRoundingModeRTNINTEL = 5621, - ExecutionModeFloatingPointModeALTINTEL = 5622, - ExecutionModeFloatingPointModeIEEEINTEL = 5623, - ExecutionModeMaxWorkgroupSizeINTEL = 5893, - ExecutionModeMaxWorkDimINTEL = 5894, - ExecutionModeNoGlobalOffsetINTEL = 5895, - ExecutionModeNumSIMDWorkitemsINTEL = 5896, - ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903, - ExecutionModeMaximallyReconvergesKHR = 6023, - ExecutionModeFPFastMathDefault = 6028, - ExecutionModeStreamingInterfaceINTEL = 6154, - ExecutionModeRegisterMapInterfaceINTEL = 6160, - ExecutionModeNamedBarrierCountINTEL = 6417, - ExecutionModeMaximumRegistersINTEL = 6461, - ExecutionModeMaximumRegistersIdINTEL = 6462, - ExecutionModeNamedMaximumRegistersINTEL = 6463, - ExecutionModeMax = 0x7fffffff, -}; - -enum StorageClass { - StorageClassUniformConstant = 0, - StorageClassInput = 1, - StorageClassUniform = 2, - StorageClassOutput = 3, - StorageClassWorkgroup = 4, - StorageClassCrossWorkgroup = 5, - StorageClassPrivate = 6, - StorageClassFunction = 7, - StorageClassGeneric = 8, - StorageClassPushConstant = 9, - StorageClassAtomicCounter = 10, - StorageClassImage = 11, - StorageClassStorageBuffer = 12, - StorageClassTileImageEXT = 4172, - StorageClassNodePayloadAMDX = 5068, - StorageClassCallableDataKHR = 5328, - StorageClassCallableDataNV = 5328, - StorageClassIncomingCallableDataKHR = 5329, - StorageClassIncomingCallableDataNV = 5329, - StorageClassRayPayloadKHR = 5338, - StorageClassRayPayloadNV = 5338, - StorageClassHitAttributeKHR = 5339, - StorageClassHitAttributeNV = 5339, - StorageClassIncomingRayPayloadKHR = 5342, - StorageClassIncomingRayPayloadNV = 5342, - StorageClassShaderRecordBufferKHR = 5343, - StorageClassShaderRecordBufferNV = 5343, - StorageClassPhysicalStorageBuffer = 5349, - StorageClassPhysicalStorageBufferEXT = 5349, - StorageClassHitObjectAttributeNV = 5385, - StorageClassTaskPayloadWorkgroupEXT = 5402, - StorageClassCodeSectionINTEL = 5605, - StorageClassDeviceOnlyINTEL = 5936, - StorageClassHostOnlyINTEL = 5937, - StorageClassMax = 0x7fffffff, -}; - -enum Dim { - Dim1D = 0, - Dim2D = 1, - Dim3D = 2, - DimCube = 3, - DimRect = 4, - DimBuffer = 5, - DimSubpassData = 6, - DimTileImageDataEXT = 4173, - DimMax = 0x7fffffff, -}; - -enum SamplerAddressingMode { - SamplerAddressingModeNone = 0, - SamplerAddressingModeClampToEdge = 1, - SamplerAddressingModeClamp = 2, - SamplerAddressingModeRepeat = 3, - SamplerAddressingModeRepeatMirrored = 4, - SamplerAddressingModeMax = 0x7fffffff, -}; - -enum SamplerFilterMode { - SamplerFilterModeNearest = 0, - SamplerFilterModeLinear = 1, - SamplerFilterModeMax = 0x7fffffff, -}; - -enum ImageFormat { - ImageFormatUnknown = 0, - ImageFormatRgba32f = 1, - ImageFormatRgba16f = 2, - ImageFormatR32f = 3, - ImageFormatRgba8 = 4, - ImageFormatRgba8Snorm = 5, - ImageFormatRg32f = 6, - ImageFormatRg16f = 7, - ImageFormatR11fG11fB10f = 8, - ImageFormatR16f = 9, - ImageFormatRgba16 = 10, - ImageFormatRgb10A2 = 11, - ImageFormatRg16 = 12, - ImageFormatRg8 = 13, - ImageFormatR16 = 14, - ImageFormatR8 = 15, - ImageFormatRgba16Snorm = 16, - ImageFormatRg16Snorm = 17, - ImageFormatRg8Snorm = 18, - ImageFormatR16Snorm = 19, - ImageFormatR8Snorm = 20, - ImageFormatRgba32i = 21, - ImageFormatRgba16i = 22, - ImageFormatRgba8i = 23, - ImageFormatR32i = 24, - ImageFormatRg32i = 25, - ImageFormatRg16i = 26, - ImageFormatRg8i = 27, - ImageFormatR16i = 28, - ImageFormatR8i = 29, - ImageFormatRgba32ui = 30, - ImageFormatRgba16ui = 31, - ImageFormatRgba8ui = 32, - ImageFormatR32ui = 33, - ImageFormatRgb10a2ui = 34, - ImageFormatRg32ui = 35, - ImageFormatRg16ui = 36, - ImageFormatRg8ui = 37, - ImageFormatR16ui = 38, - ImageFormatR8ui = 39, - ImageFormatR64ui = 40, - ImageFormatR64i = 41, - ImageFormatMax = 0x7fffffff, -}; - -enum ImageChannelOrder { - ImageChannelOrderR = 0, - ImageChannelOrderA = 1, - ImageChannelOrderRG = 2, - ImageChannelOrderRA = 3, - ImageChannelOrderRGB = 4, - ImageChannelOrderRGBA = 5, - ImageChannelOrderBGRA = 6, - ImageChannelOrderARGB = 7, - ImageChannelOrderIntensity = 8, - ImageChannelOrderLuminance = 9, - ImageChannelOrderRx = 10, - ImageChannelOrderRGx = 11, - ImageChannelOrderRGBx = 12, - ImageChannelOrderDepth = 13, - ImageChannelOrderDepthStencil = 14, - ImageChannelOrdersRGB = 15, - ImageChannelOrdersRGBx = 16, - ImageChannelOrdersRGBA = 17, - ImageChannelOrdersBGRA = 18, - ImageChannelOrderABGR = 19, - ImageChannelOrderMax = 0x7fffffff, -}; - -enum ImageChannelDataType { - ImageChannelDataTypeSnormInt8 = 0, - ImageChannelDataTypeSnormInt16 = 1, - ImageChannelDataTypeUnormInt8 = 2, - ImageChannelDataTypeUnormInt16 = 3, - ImageChannelDataTypeUnormShort565 = 4, - ImageChannelDataTypeUnormShort555 = 5, - ImageChannelDataTypeUnormInt101010 = 6, - ImageChannelDataTypeSignedInt8 = 7, - ImageChannelDataTypeSignedInt16 = 8, - ImageChannelDataTypeSignedInt32 = 9, - ImageChannelDataTypeUnsignedInt8 = 10, - ImageChannelDataTypeUnsignedInt16 = 11, - ImageChannelDataTypeUnsignedInt32 = 12, - ImageChannelDataTypeHalfFloat = 13, - ImageChannelDataTypeFloat = 14, - ImageChannelDataTypeUnormInt24 = 15, - ImageChannelDataTypeUnormInt101010_2 = 16, - ImageChannelDataTypeUnsignedIntRaw10EXT = 19, - ImageChannelDataTypeUnsignedIntRaw12EXT = 20, - ImageChannelDataTypeUnormInt2_101010EXT = 21, - ImageChannelDataTypeMax = 0x7fffffff, -}; - -enum ImageOperandsShift { - ImageOperandsBiasShift = 0, - ImageOperandsLodShift = 1, - ImageOperandsGradShift = 2, - ImageOperandsConstOffsetShift = 3, - ImageOperandsOffsetShift = 4, - ImageOperandsConstOffsetsShift = 5, - ImageOperandsSampleShift = 6, - ImageOperandsMinLodShift = 7, - ImageOperandsMakeTexelAvailableShift = 8, - ImageOperandsMakeTexelAvailableKHRShift = 8, - ImageOperandsMakeTexelVisibleShift = 9, - ImageOperandsMakeTexelVisibleKHRShift = 9, - ImageOperandsNonPrivateTexelShift = 10, - ImageOperandsNonPrivateTexelKHRShift = 10, - ImageOperandsVolatileTexelShift = 11, - ImageOperandsVolatileTexelKHRShift = 11, - ImageOperandsSignExtendShift = 12, - ImageOperandsZeroExtendShift = 13, - ImageOperandsNontemporalShift = 14, - ImageOperandsOffsetsShift = 16, - ImageOperandsMax = 0x7fffffff, -}; - -enum ImageOperandsMask : unsigned { - ImageOperandsMaskNone = 0, - ImageOperandsBiasMask = 0x00000001, - ImageOperandsLodMask = 0x00000002, - ImageOperandsGradMask = 0x00000004, - ImageOperandsConstOffsetMask = 0x00000008, - ImageOperandsOffsetMask = 0x00000010, - ImageOperandsConstOffsetsMask = 0x00000020, - ImageOperandsSampleMask = 0x00000040, - ImageOperandsMinLodMask = 0x00000080, - ImageOperandsMakeTexelAvailableMask = 0x00000100, - ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, - ImageOperandsMakeTexelVisibleMask = 0x00000200, - ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, - ImageOperandsNonPrivateTexelMask = 0x00000400, - ImageOperandsNonPrivateTexelKHRMask = 0x00000400, - ImageOperandsVolatileTexelMask = 0x00000800, - ImageOperandsVolatileTexelKHRMask = 0x00000800, - ImageOperandsSignExtendMask = 0x00001000, - ImageOperandsZeroExtendMask = 0x00002000, - ImageOperandsNontemporalMask = 0x00004000, - ImageOperandsOffsetsMask = 0x00010000, -}; - -enum FPFastMathModeShift { - FPFastMathModeNotNaNShift = 0, - FPFastMathModeNotInfShift = 1, - FPFastMathModeNSZShift = 2, - FPFastMathModeAllowRecipShift = 3, - FPFastMathModeFastShift = 4, - FPFastMathModeAllowContractShift = 16, - FPFastMathModeAllowContractFastINTELShift = 16, - FPFastMathModeAllowReassocShift = 17, - FPFastMathModeAllowReassocINTELShift = 17, - FPFastMathModeAllowTransformShift = 18, - FPFastMathModeMax = 0x7fffffff, -}; - -enum FPFastMathModeMask : unsigned { - FPFastMathModeMaskNone = 0, - FPFastMathModeNotNaNMask = 0x00000001, - FPFastMathModeNotInfMask = 0x00000002, - FPFastMathModeNSZMask = 0x00000004, - FPFastMathModeAllowRecipMask = 0x00000008, - FPFastMathModeFastMask = 0x00000010, - FPFastMathModeAllowContractMask = 0x00010000, - FPFastMathModeAllowContractFastINTELMask = 0x00010000, - FPFastMathModeAllowReassocMask = 0x00020000, - FPFastMathModeAllowReassocINTELMask = 0x00020000, - FPFastMathModeAllowTransformMask = 0x00040000, -}; - -enum FPRoundingMode { - FPRoundingModeRTE = 0, - FPRoundingModeRTZ = 1, - FPRoundingModeRTP = 2, - FPRoundingModeRTN = 3, - FPRoundingModeMax = 0x7fffffff, -}; - -enum LinkageType { - LinkageTypeExport = 0, - LinkageTypeImport = 1, - LinkageTypeLinkOnceODR = 2, - LinkageTypeMax = 0x7fffffff, -}; - -enum AccessQualifier { - AccessQualifierReadOnly = 0, - AccessQualifierWriteOnly = 1, - AccessQualifierReadWrite = 2, - AccessQualifierMax = 0x7fffffff, -}; - -enum FunctionParameterAttribute { - FunctionParameterAttributeZext = 0, - FunctionParameterAttributeSext = 1, - FunctionParameterAttributeByVal = 2, - FunctionParameterAttributeSret = 3, - FunctionParameterAttributeNoAlias = 4, - FunctionParameterAttributeNoCapture = 5, - FunctionParameterAttributeNoWrite = 6, - FunctionParameterAttributeNoReadWrite = 7, - FunctionParameterAttributeRuntimeAlignedINTEL = 5940, - FunctionParameterAttributeMax = 0x7fffffff, -}; - -enum Decoration { - DecorationRelaxedPrecision = 0, - DecorationSpecId = 1, - DecorationBlock = 2, - DecorationBufferBlock = 3, - DecorationRowMajor = 4, - DecorationColMajor = 5, - DecorationArrayStride = 6, - DecorationMatrixStride = 7, - DecorationGLSLShared = 8, - DecorationGLSLPacked = 9, - DecorationCPacked = 10, - DecorationBuiltIn = 11, - DecorationNoPerspective = 13, - DecorationFlat = 14, - DecorationPatch = 15, - DecorationCentroid = 16, - DecorationSample = 17, - DecorationInvariant = 18, - DecorationRestrict = 19, - DecorationAliased = 20, - DecorationVolatile = 21, - DecorationConstant = 22, - DecorationCoherent = 23, - DecorationNonWritable = 24, - DecorationNonReadable = 25, - DecorationUniform = 26, - DecorationUniformId = 27, - DecorationSaturatedConversion = 28, - DecorationStream = 29, - DecorationLocation = 30, - DecorationComponent = 31, - DecorationIndex = 32, - DecorationBinding = 33, - DecorationDescriptorSet = 34, - DecorationOffset = 35, - DecorationXfbBuffer = 36, - DecorationXfbStride = 37, - DecorationFuncParamAttr = 38, - DecorationFPRoundingMode = 39, - DecorationFPFastMathMode = 40, - DecorationLinkageAttributes = 41, - DecorationNoContraction = 42, - DecorationInputAttachmentIndex = 43, - DecorationAlignment = 44, - DecorationMaxByteOffset = 45, - DecorationAlignmentId = 46, - DecorationMaxByteOffsetId = 47, - DecorationNoSignedWrap = 4469, - DecorationNoUnsignedWrap = 4470, - DecorationWeightTextureQCOM = 4487, - DecorationBlockMatchTextureQCOM = 4488, - DecorationBlockMatchSamplerQCOM = 4499, - DecorationExplicitInterpAMD = 4999, - DecorationNodeSharesPayloadLimitsWithAMDX = 5019, - DecorationNodeMaxPayloadsAMDX = 5020, - DecorationTrackFinishWritingAMDX = 5078, - DecorationPayloadNodeNameAMDX = 5091, - DecorationPayloadNodeBaseIndexAMDX = 5098, - DecorationPayloadNodeSparseArrayAMDX = 5099, - DecorationPayloadNodeArraySizeAMDX = 5100, - DecorationPayloadDispatchIndirectAMDX = 5105, - DecorationOverrideCoverageNV = 5248, - DecorationPassthroughNV = 5250, - DecorationViewportRelativeNV = 5252, - DecorationSecondaryViewportRelativeNV = 5256, - DecorationPerPrimitiveEXT = 5271, - DecorationPerPrimitiveNV = 5271, - DecorationPerViewNV = 5272, - DecorationPerTaskNV = 5273, - DecorationPerVertexKHR = 5285, - DecorationPerVertexNV = 5285, - DecorationNonUniform = 5300, - DecorationNonUniformEXT = 5300, - DecorationRestrictPointer = 5355, - DecorationRestrictPointerEXT = 5355, - DecorationAliasedPointer = 5356, - DecorationAliasedPointerEXT = 5356, - DecorationHitObjectShaderRecordBufferNV = 5386, - DecorationBindlessSamplerNV = 5398, - DecorationBindlessImageNV = 5399, - DecorationBoundSamplerNV = 5400, - DecorationBoundImageNV = 5401, - DecorationSIMTCallINTEL = 5599, - DecorationReferencedIndirectlyINTEL = 5602, - DecorationClobberINTEL = 5607, - DecorationSideEffectsINTEL = 5608, - DecorationVectorComputeVariableINTEL = 5624, - DecorationFuncParamIOKindINTEL = 5625, - DecorationVectorComputeFunctionINTEL = 5626, - DecorationStackCallINTEL = 5627, - DecorationGlobalVariableOffsetINTEL = 5628, - DecorationCounterBuffer = 5634, - DecorationHlslCounterBufferGOOGLE = 5634, - DecorationHlslSemanticGOOGLE = 5635, - DecorationUserSemantic = 5635, - DecorationUserTypeGOOGLE = 5636, - DecorationFunctionRoundingModeINTEL = 5822, - DecorationFunctionDenormModeINTEL = 5823, - DecorationRegisterINTEL = 5825, - DecorationMemoryINTEL = 5826, - DecorationNumbanksINTEL = 5827, - DecorationBankwidthINTEL = 5828, - DecorationMaxPrivateCopiesINTEL = 5829, - DecorationSinglepumpINTEL = 5830, - DecorationDoublepumpINTEL = 5831, - DecorationMaxReplicatesINTEL = 5832, - DecorationSimpleDualPortINTEL = 5833, - DecorationMergeINTEL = 5834, - DecorationBankBitsINTEL = 5835, - DecorationForcePow2DepthINTEL = 5836, - DecorationStridesizeINTEL = 5883, - DecorationWordsizeINTEL = 5884, - DecorationTrueDualPortINTEL = 5885, - DecorationBurstCoalesceINTEL = 5899, - DecorationCacheSizeINTEL = 5900, - DecorationDontStaticallyCoalesceINTEL = 5901, - DecorationPrefetchINTEL = 5902, - DecorationStallEnableINTEL = 5905, - DecorationFuseLoopsInFunctionINTEL = 5907, - DecorationMathOpDSPModeINTEL = 5909, - DecorationAliasScopeINTEL = 5914, - DecorationNoAliasINTEL = 5915, - DecorationInitiationIntervalINTEL = 5917, - DecorationMaxConcurrencyINTEL = 5918, - DecorationPipelineEnableINTEL = 5919, - DecorationBufferLocationINTEL = 5921, - DecorationIOPipeStorageINTEL = 5944, - DecorationFunctionFloatingPointModeINTEL = 6080, - DecorationSingleElementVectorINTEL = 6085, - DecorationVectorComputeCallableFunctionINTEL = 6087, - DecorationMediaBlockIOINTEL = 6140, - DecorationStallFreeINTEL = 6151, - DecorationFPMaxErrorDecorationINTEL = 6170, - DecorationLatencyControlLabelINTEL = 6172, - DecorationLatencyControlConstraintINTEL = 6173, - DecorationConduitKernelArgumentINTEL = 6175, - DecorationRegisterMapKernelArgumentINTEL = 6176, - DecorationMMHostInterfaceAddressWidthINTEL = 6177, - DecorationMMHostInterfaceDataWidthINTEL = 6178, - DecorationMMHostInterfaceLatencyINTEL = 6179, - DecorationMMHostInterfaceReadWriteModeINTEL = 6180, - DecorationMMHostInterfaceMaxBurstINTEL = 6181, - DecorationMMHostInterfaceWaitRequestINTEL = 6182, - DecorationStableKernelArgumentINTEL = 6183, - DecorationHostAccessINTEL = 6188, - DecorationInitModeINTEL = 6190, - DecorationImplementInRegisterMapINTEL = 6191, - DecorationCacheControlLoadINTEL = 6442, - DecorationCacheControlStoreINTEL = 6443, - DecorationMax = 0x7fffffff, -}; - -enum BuiltIn { - BuiltInPosition = 0, - BuiltInPointSize = 1, - BuiltInClipDistance = 3, - BuiltInCullDistance = 4, - BuiltInVertexId = 5, - BuiltInInstanceId = 6, - BuiltInPrimitiveId = 7, - BuiltInInvocationId = 8, - BuiltInLayer = 9, - BuiltInViewportIndex = 10, - BuiltInTessLevelOuter = 11, - BuiltInTessLevelInner = 12, - BuiltInTessCoord = 13, - BuiltInPatchVertices = 14, - BuiltInFragCoord = 15, - BuiltInPointCoord = 16, - BuiltInFrontFacing = 17, - BuiltInSampleId = 18, - BuiltInSamplePosition = 19, - BuiltInSampleMask = 20, - BuiltInFragDepth = 22, - BuiltInHelperInvocation = 23, - BuiltInNumWorkgroups = 24, - BuiltInWorkgroupSize = 25, - BuiltInWorkgroupId = 26, - BuiltInLocalInvocationId = 27, - BuiltInGlobalInvocationId = 28, - BuiltInLocalInvocationIndex = 29, - BuiltInWorkDim = 30, - BuiltInGlobalSize = 31, - BuiltInEnqueuedWorkgroupSize = 32, - BuiltInGlobalOffset = 33, - BuiltInGlobalLinearId = 34, - BuiltInSubgroupSize = 36, - BuiltInSubgroupMaxSize = 37, - BuiltInNumSubgroups = 38, - BuiltInNumEnqueuedSubgroups = 39, - BuiltInSubgroupId = 40, - BuiltInSubgroupLocalInvocationId = 41, - BuiltInVertexIndex = 42, - BuiltInInstanceIndex = 43, - BuiltInCoreIDARM = 4160, - BuiltInCoreCountARM = 4161, - BuiltInCoreMaxIDARM = 4162, - BuiltInWarpIDARM = 4163, - BuiltInWarpMaxIDARM = 4164, - BuiltInSubgroupEqMask = 4416, - BuiltInSubgroupEqMaskKHR = 4416, - BuiltInSubgroupGeMask = 4417, - BuiltInSubgroupGeMaskKHR = 4417, - BuiltInSubgroupGtMask = 4418, - BuiltInSubgroupGtMaskKHR = 4418, - BuiltInSubgroupLeMask = 4419, - BuiltInSubgroupLeMaskKHR = 4419, - BuiltInSubgroupLtMask = 4420, - BuiltInSubgroupLtMaskKHR = 4420, - BuiltInBaseVertex = 4424, - BuiltInBaseInstance = 4425, - BuiltInDrawIndex = 4426, - BuiltInPrimitiveShadingRateKHR = 4432, - BuiltInDeviceIndex = 4438, - BuiltInViewIndex = 4440, - BuiltInShadingRateKHR = 4444, - BuiltInBaryCoordNoPerspAMD = 4992, - BuiltInBaryCoordNoPerspCentroidAMD = 4993, - BuiltInBaryCoordNoPerspSampleAMD = 4994, - BuiltInBaryCoordSmoothAMD = 4995, - BuiltInBaryCoordSmoothCentroidAMD = 4996, - BuiltInBaryCoordSmoothSampleAMD = 4997, - BuiltInBaryCoordPullModelAMD = 4998, - BuiltInFragStencilRefEXT = 5014, - BuiltInRemainingRecursionLevelsAMDX = 5021, - BuiltInShaderIndexAMDX = 5073, - BuiltInViewportMaskNV = 5253, - BuiltInSecondaryPositionNV = 5257, - BuiltInSecondaryViewportMaskNV = 5258, - BuiltInPositionPerViewNV = 5261, - BuiltInViewportMaskPerViewNV = 5262, - BuiltInFullyCoveredEXT = 5264, - BuiltInTaskCountNV = 5274, - BuiltInPrimitiveCountNV = 5275, - BuiltInPrimitiveIndicesNV = 5276, - BuiltInClipDistancePerViewNV = 5277, - BuiltInCullDistancePerViewNV = 5278, - BuiltInLayerPerViewNV = 5279, - BuiltInMeshViewCountNV = 5280, - BuiltInMeshViewIndicesNV = 5281, - BuiltInBaryCoordKHR = 5286, - BuiltInBaryCoordNV = 5286, - BuiltInBaryCoordNoPerspKHR = 5287, - BuiltInBaryCoordNoPerspNV = 5287, - BuiltInFragSizeEXT = 5292, - BuiltInFragmentSizeNV = 5292, - BuiltInFragInvocationCountEXT = 5293, - BuiltInInvocationsPerPixelNV = 5293, - BuiltInPrimitivePointIndicesEXT = 5294, - BuiltInPrimitiveLineIndicesEXT = 5295, - BuiltInPrimitiveTriangleIndicesEXT = 5296, - BuiltInCullPrimitiveEXT = 5299, - BuiltInLaunchIdKHR = 5319, - BuiltInLaunchIdNV = 5319, - BuiltInLaunchSizeKHR = 5320, - BuiltInLaunchSizeNV = 5320, - BuiltInWorldRayOriginKHR = 5321, - BuiltInWorldRayOriginNV = 5321, - BuiltInWorldRayDirectionKHR = 5322, - BuiltInWorldRayDirectionNV = 5322, - BuiltInObjectRayOriginKHR = 5323, - BuiltInObjectRayOriginNV = 5323, - BuiltInObjectRayDirectionKHR = 5324, - BuiltInObjectRayDirectionNV = 5324, - BuiltInRayTminKHR = 5325, - BuiltInRayTminNV = 5325, - BuiltInRayTmaxKHR = 5326, - BuiltInRayTmaxNV = 5326, - BuiltInInstanceCustomIndexKHR = 5327, - BuiltInInstanceCustomIndexNV = 5327, - BuiltInObjectToWorldKHR = 5330, - BuiltInObjectToWorldNV = 5330, - BuiltInWorldToObjectKHR = 5331, - BuiltInWorldToObjectNV = 5331, - BuiltInHitTNV = 5332, - BuiltInHitKindKHR = 5333, - BuiltInHitKindNV = 5333, - BuiltInCurrentRayTimeNV = 5334, - BuiltInHitTriangleVertexPositionsKHR = 5335, - BuiltInHitMicroTriangleVertexPositionsNV = 5337, - BuiltInHitMicroTriangleVertexBarycentricsNV = 5344, - BuiltInIncomingRayFlagsKHR = 5351, - BuiltInIncomingRayFlagsNV = 5351, - BuiltInRayGeometryIndexKHR = 5352, - BuiltInWarpsPerSMNV = 5374, - BuiltInSMCountNV = 5375, - BuiltInWarpIDNV = 5376, - BuiltInSMIDNV = 5377, - BuiltInHitKindFrontFacingMicroTriangleNV = 5405, - BuiltInHitKindBackFacingMicroTriangleNV = 5406, - BuiltInCullMaskKHR = 6021, - BuiltInMax = 0x7fffffff, -}; - -enum SelectionControlShift { - SelectionControlFlattenShift = 0, - SelectionControlDontFlattenShift = 1, - SelectionControlMax = 0x7fffffff, -}; - -enum SelectionControlMask : unsigned { - SelectionControlMaskNone = 0, - SelectionControlFlattenMask = 0x00000001, - SelectionControlDontFlattenMask = 0x00000002, -}; - -enum LoopControlShift { - LoopControlUnrollShift = 0, - LoopControlDontUnrollShift = 1, - LoopControlDependencyInfiniteShift = 2, - LoopControlDependencyLengthShift = 3, - LoopControlMinIterationsShift = 4, - LoopControlMaxIterationsShift = 5, - LoopControlIterationMultipleShift = 6, - LoopControlPeelCountShift = 7, - LoopControlPartialCountShift = 8, - LoopControlInitiationIntervalINTELShift = 16, - LoopControlMaxConcurrencyINTELShift = 17, - LoopControlDependencyArrayINTELShift = 18, - LoopControlPipelineEnableINTELShift = 19, - LoopControlLoopCoalesceINTELShift = 20, - LoopControlMaxInterleavingINTELShift = 21, - LoopControlSpeculatedIterationsINTELShift = 22, - LoopControlNoFusionINTELShift = 23, - LoopControlLoopCountINTELShift = 24, - LoopControlMaxReinvocationDelayINTELShift = 25, - LoopControlMax = 0x7fffffff, -}; - -enum LoopControlMask : unsigned { - LoopControlMaskNone = 0, - LoopControlUnrollMask = 0x00000001, - LoopControlDontUnrollMask = 0x00000002, - LoopControlDependencyInfiniteMask = 0x00000004, - LoopControlDependencyLengthMask = 0x00000008, - LoopControlMinIterationsMask = 0x00000010, - LoopControlMaxIterationsMask = 0x00000020, - LoopControlIterationMultipleMask = 0x00000040, - LoopControlPeelCountMask = 0x00000080, - LoopControlPartialCountMask = 0x00000100, - LoopControlInitiationIntervalINTELMask = 0x00010000, - LoopControlMaxConcurrencyINTELMask = 0x00020000, - LoopControlDependencyArrayINTELMask = 0x00040000, - LoopControlPipelineEnableINTELMask = 0x00080000, - LoopControlLoopCoalesceINTELMask = 0x00100000, - LoopControlMaxInterleavingINTELMask = 0x00200000, - LoopControlSpeculatedIterationsINTELMask = 0x00400000, - LoopControlNoFusionINTELMask = 0x00800000, - LoopControlLoopCountINTELMask = 0x01000000, - LoopControlMaxReinvocationDelayINTELMask = 0x02000000, -}; - -enum FunctionControlShift { - FunctionControlInlineShift = 0, - FunctionControlDontInlineShift = 1, - FunctionControlPureShift = 2, - FunctionControlConstShift = 3, - FunctionControlOptNoneEXTShift = 16, - FunctionControlOptNoneINTELShift = 16, - FunctionControlMax = 0x7fffffff, -}; - -enum FunctionControlMask : unsigned { - FunctionControlMaskNone = 0, - FunctionControlInlineMask = 0x00000001, - FunctionControlDontInlineMask = 0x00000002, - FunctionControlPureMask = 0x00000004, - FunctionControlConstMask = 0x00000008, - FunctionControlOptNoneEXTMask = 0x00010000, - FunctionControlOptNoneINTELMask = 0x00010000, -}; - -enum MemorySemanticsShift { - MemorySemanticsAcquireShift = 1, - MemorySemanticsReleaseShift = 2, - MemorySemanticsAcquireReleaseShift = 3, - MemorySemanticsSequentiallyConsistentShift = 4, - MemorySemanticsUniformMemoryShift = 6, - MemorySemanticsSubgroupMemoryShift = 7, - MemorySemanticsWorkgroupMemoryShift = 8, - MemorySemanticsCrossWorkgroupMemoryShift = 9, - MemorySemanticsAtomicCounterMemoryShift = 10, - MemorySemanticsImageMemoryShift = 11, - MemorySemanticsOutputMemoryShift = 12, - MemorySemanticsOutputMemoryKHRShift = 12, - MemorySemanticsMakeAvailableShift = 13, - MemorySemanticsMakeAvailableKHRShift = 13, - MemorySemanticsMakeVisibleShift = 14, - MemorySemanticsMakeVisibleKHRShift = 14, - MemorySemanticsVolatileShift = 15, - MemorySemanticsMax = 0x7fffffff, -}; - -enum MemorySemanticsMask : unsigned { - MemorySemanticsMaskNone = 0, - MemorySemanticsAcquireMask = 0x00000002, - MemorySemanticsReleaseMask = 0x00000004, - MemorySemanticsAcquireReleaseMask = 0x00000008, - MemorySemanticsSequentiallyConsistentMask = 0x00000010, - MemorySemanticsUniformMemoryMask = 0x00000040, - MemorySemanticsSubgroupMemoryMask = 0x00000080, - MemorySemanticsWorkgroupMemoryMask = 0x00000100, - MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, - MemorySemanticsAtomicCounterMemoryMask = 0x00000400, - MemorySemanticsImageMemoryMask = 0x00000800, - MemorySemanticsOutputMemoryMask = 0x00001000, - MemorySemanticsOutputMemoryKHRMask = 0x00001000, - MemorySemanticsMakeAvailableMask = 0x00002000, - MemorySemanticsMakeAvailableKHRMask = 0x00002000, - MemorySemanticsMakeVisibleMask = 0x00004000, - MemorySemanticsMakeVisibleKHRMask = 0x00004000, - MemorySemanticsVolatileMask = 0x00008000, -}; - -enum MemoryAccessShift { - MemoryAccessVolatileShift = 0, - MemoryAccessAlignedShift = 1, - MemoryAccessNontemporalShift = 2, - MemoryAccessMakePointerAvailableShift = 3, - MemoryAccessMakePointerAvailableKHRShift = 3, - MemoryAccessMakePointerVisibleShift = 4, - MemoryAccessMakePointerVisibleKHRShift = 4, - MemoryAccessNonPrivatePointerShift = 5, - MemoryAccessNonPrivatePointerKHRShift = 5, - MemoryAccessAliasScopeINTELMaskShift = 16, - MemoryAccessNoAliasINTELMaskShift = 17, - MemoryAccessMax = 0x7fffffff, -}; - -enum MemoryAccessMask : unsigned { - MemoryAccessMaskNone = 0, - MemoryAccessVolatileMask = 0x00000001, - MemoryAccessAlignedMask = 0x00000002, - MemoryAccessNontemporalMask = 0x00000004, - MemoryAccessMakePointerAvailableMask = 0x00000008, - MemoryAccessMakePointerAvailableKHRMask = 0x00000008, - MemoryAccessMakePointerVisibleMask = 0x00000010, - MemoryAccessMakePointerVisibleKHRMask = 0x00000010, - MemoryAccessNonPrivatePointerMask = 0x00000020, - MemoryAccessNonPrivatePointerKHRMask = 0x00000020, - MemoryAccessAliasScopeINTELMaskMask = 0x00010000, - MemoryAccessNoAliasINTELMaskMask = 0x00020000, -}; - -enum Scope { - ScopeCrossDevice = 0, - ScopeDevice = 1, - ScopeWorkgroup = 2, - ScopeSubgroup = 3, - ScopeInvocation = 4, - ScopeQueueFamily = 5, - ScopeQueueFamilyKHR = 5, - ScopeShaderCallKHR = 6, - ScopeMax = 0x7fffffff, -}; - -enum GroupOperation { - GroupOperationReduce = 0, - GroupOperationInclusiveScan = 1, - GroupOperationExclusiveScan = 2, - GroupOperationClusteredReduce = 3, - GroupOperationPartitionedReduceNV = 6, - GroupOperationPartitionedInclusiveScanNV = 7, - GroupOperationPartitionedExclusiveScanNV = 8, - GroupOperationMax = 0x7fffffff, -}; - -enum KernelEnqueueFlags { - KernelEnqueueFlagsNoWait = 0, - KernelEnqueueFlagsWaitKernel = 1, - KernelEnqueueFlagsWaitWorkGroup = 2, - KernelEnqueueFlagsMax = 0x7fffffff, -}; - -enum KernelProfilingInfoShift { - KernelProfilingInfoCmdExecTimeShift = 0, - KernelProfilingInfoMax = 0x7fffffff, -}; - -enum KernelProfilingInfoMask : unsigned { - KernelProfilingInfoMaskNone = 0, - KernelProfilingInfoCmdExecTimeMask = 0x00000001, -}; - -enum Capability { - CapabilityMatrix = 0, - CapabilityShader = 1, - CapabilityGeometry = 2, - CapabilityTessellation = 3, - CapabilityAddresses = 4, - CapabilityLinkage = 5, - CapabilityKernel = 6, - CapabilityVector16 = 7, - CapabilityFloat16Buffer = 8, - CapabilityFloat16 = 9, - CapabilityFloat64 = 10, - CapabilityInt64 = 11, - CapabilityInt64Atomics = 12, - CapabilityImageBasic = 13, - CapabilityImageReadWrite = 14, - CapabilityImageMipmap = 15, - CapabilityPipes = 17, - CapabilityGroups = 18, - CapabilityDeviceEnqueue = 19, - CapabilityLiteralSampler = 20, - CapabilityAtomicStorage = 21, - CapabilityInt16 = 22, - CapabilityTessellationPointSize = 23, - CapabilityGeometryPointSize = 24, - CapabilityImageGatherExtended = 25, - CapabilityStorageImageMultisample = 27, - CapabilityUniformBufferArrayDynamicIndexing = 28, - CapabilitySampledImageArrayDynamicIndexing = 29, - CapabilityStorageBufferArrayDynamicIndexing = 30, - CapabilityStorageImageArrayDynamicIndexing = 31, - CapabilityClipDistance = 32, - CapabilityCullDistance = 33, - CapabilityImageCubeArray = 34, - CapabilitySampleRateShading = 35, - CapabilityImageRect = 36, - CapabilitySampledRect = 37, - CapabilityGenericPointer = 38, - CapabilityInt8 = 39, - CapabilityInputAttachment = 40, - CapabilitySparseResidency = 41, - CapabilityMinLod = 42, - CapabilitySampled1D = 43, - CapabilityImage1D = 44, - CapabilitySampledCubeArray = 45, - CapabilitySampledBuffer = 46, - CapabilityImageBuffer = 47, - CapabilityImageMSArray = 48, - CapabilityStorageImageExtendedFormats = 49, - CapabilityImageQuery = 50, - CapabilityDerivativeControl = 51, - CapabilityInterpolationFunction = 52, - CapabilityTransformFeedback = 53, - CapabilityGeometryStreams = 54, - CapabilityStorageImageReadWithoutFormat = 55, - CapabilityStorageImageWriteWithoutFormat = 56, - CapabilityMultiViewport = 57, - CapabilitySubgroupDispatch = 58, - CapabilityNamedBarrier = 59, - CapabilityPipeStorage = 60, - CapabilityGroupNonUniform = 61, - CapabilityGroupNonUniformVote = 62, - CapabilityGroupNonUniformArithmetic = 63, - CapabilityGroupNonUniformBallot = 64, - CapabilityGroupNonUniformShuffle = 65, - CapabilityGroupNonUniformShuffleRelative = 66, - CapabilityGroupNonUniformClustered = 67, - CapabilityGroupNonUniformQuad = 68, - CapabilityShaderLayer = 69, - CapabilityShaderViewportIndex = 70, - CapabilityUniformDecoration = 71, - CapabilityCoreBuiltinsARM = 4165, - CapabilityTileImageColorReadAccessEXT = 4166, - CapabilityTileImageDepthReadAccessEXT = 4167, - CapabilityTileImageStencilReadAccessEXT = 4168, - CapabilityCooperativeMatrixLayoutsARM = 4201, - CapabilityFragmentShadingRateKHR = 4422, - CapabilitySubgroupBallotKHR = 4423, - CapabilityDrawParameters = 4427, - CapabilityWorkgroupMemoryExplicitLayoutKHR = 4428, - CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429, - CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430, - CapabilitySubgroupVoteKHR = 4431, - CapabilityStorageBuffer16BitAccess = 4433, - CapabilityStorageUniformBufferBlock16 = 4433, - CapabilityStorageUniform16 = 4434, - CapabilityUniformAndStorageBuffer16BitAccess = 4434, - CapabilityStoragePushConstant16 = 4435, - CapabilityStorageInputOutput16 = 4436, - CapabilityDeviceGroup = 4437, - CapabilityMultiView = 4439, - CapabilityVariablePointersStorageBuffer = 4441, - CapabilityVariablePointers = 4442, - CapabilityAtomicStorageOps = 4445, - CapabilitySampleMaskPostDepthCoverage = 4447, - CapabilityStorageBuffer8BitAccess = 4448, - CapabilityUniformAndStorageBuffer8BitAccess = 4449, - CapabilityStoragePushConstant8 = 4450, - CapabilityDenormPreserve = 4464, - CapabilityDenormFlushToZero = 4465, - CapabilitySignedZeroInfNanPreserve = 4466, - CapabilityRoundingModeRTE = 4467, - CapabilityRoundingModeRTZ = 4468, - CapabilityRayQueryProvisionalKHR = 4471, - CapabilityRayQueryKHR = 4472, - CapabilityUntypedPointersKHR = 4473, - CapabilityRayTraversalPrimitiveCullingKHR = 4478, - CapabilityRayTracingKHR = 4479, - CapabilityTextureSampleWeightedQCOM = 4484, - CapabilityTextureBoxFilterQCOM = 4485, - CapabilityTextureBlockMatchQCOM = 4486, - CapabilityTextureBlockMatch2QCOM = 4498, - CapabilityFloat16ImageAMD = 5008, - CapabilityImageGatherBiasLodAMD = 5009, - CapabilityFragmentMaskAMD = 5010, - CapabilityStencilExportEXT = 5013, - CapabilityImageReadWriteLodAMD = 5015, - CapabilityInt64ImageEXT = 5016, - CapabilityShaderClockKHR = 5055, - CapabilityShaderEnqueueAMDX = 5067, - CapabilityQuadControlKHR = 5087, - CapabilitySampleMaskOverrideCoverageNV = 5249, - CapabilityGeometryShaderPassthroughNV = 5251, - CapabilityShaderViewportIndexLayerEXT = 5254, - CapabilityShaderViewportIndexLayerNV = 5254, - CapabilityShaderViewportMaskNV = 5255, - CapabilityShaderStereoViewNV = 5259, - CapabilityPerViewAttributesNV = 5260, - CapabilityFragmentFullyCoveredEXT = 5265, - CapabilityMeshShadingNV = 5266, - CapabilityImageFootprintNV = 5282, - CapabilityMeshShadingEXT = 5283, - CapabilityFragmentBarycentricKHR = 5284, - CapabilityFragmentBarycentricNV = 5284, - CapabilityComputeDerivativeGroupQuadsKHR = 5288, - CapabilityComputeDerivativeGroupQuadsNV = 5288, - CapabilityFragmentDensityEXT = 5291, - CapabilityShadingRateNV = 5291, - CapabilityGroupNonUniformPartitionedNV = 5297, - CapabilityShaderNonUniform = 5301, - CapabilityShaderNonUniformEXT = 5301, - CapabilityRuntimeDescriptorArray = 5302, - CapabilityRuntimeDescriptorArrayEXT = 5302, - CapabilityInputAttachmentArrayDynamicIndexing = 5303, - CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, - CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, - CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, - CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, - CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, - CapabilityUniformBufferArrayNonUniformIndexing = 5306, - CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, - CapabilitySampledImageArrayNonUniformIndexing = 5307, - CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, - CapabilityStorageBufferArrayNonUniformIndexing = 5308, - CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, - CapabilityStorageImageArrayNonUniformIndexing = 5309, - CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, - CapabilityInputAttachmentArrayNonUniformIndexing = 5310, - CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, - CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, - CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, - CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, - CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, - CapabilityRayTracingPositionFetchKHR = 5336, - CapabilityRayTracingNV = 5340, - CapabilityRayTracingMotionBlurNV = 5341, - CapabilityVulkanMemoryModel = 5345, - CapabilityVulkanMemoryModelKHR = 5345, - CapabilityVulkanMemoryModelDeviceScope = 5346, - CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, - CapabilityPhysicalStorageBufferAddresses = 5347, - CapabilityPhysicalStorageBufferAddressesEXT = 5347, - CapabilityComputeDerivativeGroupLinearKHR = 5350, - CapabilityComputeDerivativeGroupLinearNV = 5350, - CapabilityRayTracingProvisionalKHR = 5353, - CapabilityCooperativeMatrixNV = 5357, - CapabilityFragmentShaderSampleInterlockEXT = 5363, - CapabilityFragmentShaderShadingRateInterlockEXT = 5372, - CapabilityShaderSMBuiltinsNV = 5373, - CapabilityFragmentShaderPixelInterlockEXT = 5378, - CapabilityDemoteToHelperInvocation = 5379, - CapabilityDemoteToHelperInvocationEXT = 5379, - CapabilityDisplacementMicromapNV = 5380, - CapabilityRayTracingOpacityMicromapEXT = 5381, - CapabilityShaderInvocationReorderNV = 5383, - CapabilityBindlessTextureNV = 5390, - CapabilityRayQueryPositionFetchKHR = 5391, - CapabilityAtomicFloat16VectorNV = 5404, - CapabilityRayTracingDisplacementMicromapNV = 5409, - CapabilityRawAccessChainsNV = 5414, - CapabilityCooperativeMatrixReductionsNV = 5430, - CapabilityCooperativeMatrixConversionsNV = 5431, - CapabilityCooperativeMatrixPerElementOperationsNV = 5432, - CapabilityCooperativeMatrixTensorAddressingNV = 5433, - CapabilityCooperativeMatrixBlockLoadsNV = 5434, - CapabilityTensorAddressingNV = 5439, - CapabilitySubgroupShuffleINTEL = 5568, - CapabilitySubgroupBufferBlockIOINTEL = 5569, - CapabilitySubgroupImageBlockIOINTEL = 5570, - CapabilitySubgroupImageMediaBlockIOINTEL = 5579, - CapabilityRoundToInfinityINTEL = 5582, - CapabilityFloatingPointModeINTEL = 5583, - CapabilityIntegerFunctions2INTEL = 5584, - CapabilityFunctionPointersINTEL = 5603, - CapabilityIndirectReferencesINTEL = 5604, - CapabilityAsmINTEL = 5606, - CapabilityAtomicFloat32MinMaxEXT = 5612, - CapabilityAtomicFloat64MinMaxEXT = 5613, - CapabilityAtomicFloat16MinMaxEXT = 5616, - CapabilityVectorComputeINTEL = 5617, - CapabilityVectorAnyINTEL = 5619, - CapabilityExpectAssumeKHR = 5629, - CapabilitySubgroupAvcMotionEstimationINTEL = 5696, - CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, - CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, - CapabilityVariableLengthArrayINTEL = 5817, - CapabilityFunctionFloatControlINTEL = 5821, - CapabilityFPGAMemoryAttributesINTEL = 5824, - CapabilityFPFastMathModeINTEL = 5837, - CapabilityArbitraryPrecisionIntegersINTEL = 5844, - CapabilityArbitraryPrecisionFloatingPointINTEL = 5845, - CapabilityUnstructuredLoopControlsINTEL = 5886, - CapabilityFPGALoopControlsINTEL = 5888, - CapabilityKernelAttributesINTEL = 5892, - CapabilityFPGAKernelAttributesINTEL = 5897, - CapabilityFPGAMemoryAccessesINTEL = 5898, - CapabilityFPGAClusterAttributesINTEL = 5904, - CapabilityLoopFuseINTEL = 5906, - CapabilityFPGADSPControlINTEL = 5908, - CapabilityMemoryAccessAliasingINTEL = 5910, - CapabilityFPGAInvocationPipeliningAttributesINTEL = 5916, - CapabilityFPGABufferLocationINTEL = 5920, - CapabilityArbitraryPrecisionFixedPointINTEL = 5922, - CapabilityUSMStorageClassesINTEL = 5935, - CapabilityRuntimeAlignedAttributeINTEL = 5939, - CapabilityIOPipesINTEL = 5943, - CapabilityBlockingPipesINTEL = 5945, - CapabilityFPGARegINTEL = 5948, - CapabilityDotProductInputAll = 6016, - CapabilityDotProductInputAllKHR = 6016, - CapabilityDotProductInput4x8Bit = 6017, - CapabilityDotProductInput4x8BitKHR = 6017, - CapabilityDotProductInput4x8BitPacked = 6018, - CapabilityDotProductInput4x8BitPackedKHR = 6018, - CapabilityDotProduct = 6019, - CapabilityDotProductKHR = 6019, - CapabilityRayCullMaskKHR = 6020, - CapabilityCooperativeMatrixKHR = 6022, - CapabilityReplicatedCompositesEXT = 6024, - CapabilityBitInstructions = 6025, - CapabilityGroupNonUniformRotateKHR = 6026, - CapabilityFloatControls2 = 6029, - CapabilityAtomicFloat32AddEXT = 6033, - CapabilityAtomicFloat64AddEXT = 6034, - CapabilityLongCompositesINTEL = 6089, - CapabilityOptNoneEXT = 6094, - CapabilityOptNoneINTEL = 6094, - CapabilityAtomicFloat16AddEXT = 6095, - CapabilityDebugInfoModuleINTEL = 6114, - CapabilityBFloat16ConversionINTEL = 6115, - CapabilitySplitBarrierINTEL = 6141, - CapabilityArithmeticFenceEXT = 6144, - CapabilityFPGAClusterAttributesV2INTEL = 6150, - CapabilityFPGAKernelAttributesv2INTEL = 6161, - CapabilityFPMaxErrorINTEL = 6169, - CapabilityFPGALatencyControlINTEL = 6171, - CapabilityFPGAArgumentInterfacesINTEL = 6174, - CapabilityGlobalVariableHostAccessINTEL = 6187, - CapabilityGlobalVariableFPGADecorationsINTEL = 6189, - CapabilitySubgroupBufferPrefetchINTEL = 6220, - CapabilityGroupUniformArithmeticKHR = 6400, - CapabilityMaskedGatherScatterINTEL = 6427, - CapabilityCacheControlsINTEL = 6441, - CapabilityRegisterLimitsINTEL = 6460, - CapabilityMax = 0x7fffffff, -}; - -enum RayFlagsShift { - RayFlagsOpaqueKHRShift = 0, - RayFlagsNoOpaqueKHRShift = 1, - RayFlagsTerminateOnFirstHitKHRShift = 2, - RayFlagsSkipClosestHitShaderKHRShift = 3, - RayFlagsCullBackFacingTrianglesKHRShift = 4, - RayFlagsCullFrontFacingTrianglesKHRShift = 5, - RayFlagsCullOpaqueKHRShift = 6, - RayFlagsCullNoOpaqueKHRShift = 7, - RayFlagsSkipTrianglesKHRShift = 8, - RayFlagsSkipAABBsKHRShift = 9, - RayFlagsForceOpacityMicromap2StateEXTShift = 10, - RayFlagsMax = 0x7fffffff, -}; - -enum RayFlagsMask : unsigned { - RayFlagsMaskNone = 0, - RayFlagsOpaqueKHRMask = 0x00000001, - RayFlagsNoOpaqueKHRMask = 0x00000002, - RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, - RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, - RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, - RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, - RayFlagsCullOpaqueKHRMask = 0x00000040, - RayFlagsCullNoOpaqueKHRMask = 0x00000080, - RayFlagsSkipTrianglesKHRMask = 0x00000100, - RayFlagsSkipAABBsKHRMask = 0x00000200, - RayFlagsForceOpacityMicromap2StateEXTMask = 0x00000400, -}; - -enum RayQueryIntersection { - RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, - RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, - RayQueryIntersectionMax = 0x7fffffff, -}; - -enum RayQueryCommittedIntersectionType { - RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, - RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, - RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, - RayQueryCommittedIntersectionTypeMax = 0x7fffffff, -}; - -enum RayQueryCandidateIntersectionType { - RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, - RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, - RayQueryCandidateIntersectionTypeMax = 0x7fffffff, -}; - -enum FragmentShadingRateShift { - FragmentShadingRateVertical2PixelsShift = 0, - FragmentShadingRateVertical4PixelsShift = 1, - FragmentShadingRateHorizontal2PixelsShift = 2, - FragmentShadingRateHorizontal4PixelsShift = 3, - FragmentShadingRateMax = 0x7fffffff, -}; - -enum FragmentShadingRateMask : unsigned { - FragmentShadingRateMaskNone = 0, - FragmentShadingRateVertical2PixelsMask = 0x00000001, - FragmentShadingRateVertical4PixelsMask = 0x00000002, - FragmentShadingRateHorizontal2PixelsMask = 0x00000004, - FragmentShadingRateHorizontal4PixelsMask = 0x00000008, -}; - -enum FPDenormMode { - FPDenormModePreserve = 0, - FPDenormModeFlushToZero = 1, - FPDenormModeMax = 0x7fffffff, -}; - -enum FPOperationMode { - FPOperationModeIEEE = 0, - FPOperationModeALT = 1, - FPOperationModeMax = 0x7fffffff, -}; - -enum QuantizationModes { - QuantizationModesTRN = 0, - QuantizationModesTRN_ZERO = 1, - QuantizationModesRND = 2, - QuantizationModesRND_ZERO = 3, - QuantizationModesRND_INF = 4, - QuantizationModesRND_MIN_INF = 5, - QuantizationModesRND_CONV = 6, - QuantizationModesRND_CONV_ODD = 7, - QuantizationModesMax = 0x7fffffff, -}; - -enum OverflowModes { - OverflowModesWRAP = 0, - OverflowModesSAT = 1, - OverflowModesSAT_ZERO = 2, - OverflowModesSAT_SYM = 3, - OverflowModesMax = 0x7fffffff, -}; - -enum PackedVectorFormat { - PackedVectorFormatPackedVectorFormat4x8Bit = 0, - PackedVectorFormatPackedVectorFormat4x8BitKHR = 0, - PackedVectorFormatMax = 0x7fffffff, -}; - -enum CooperativeMatrixOperandsShift { - CooperativeMatrixOperandsMatrixASignedComponentsKHRShift = 0, - CooperativeMatrixOperandsMatrixBSignedComponentsKHRShift = 1, - CooperativeMatrixOperandsMatrixCSignedComponentsKHRShift = 2, - CooperativeMatrixOperandsMatrixResultSignedComponentsKHRShift = 3, - CooperativeMatrixOperandsSaturatingAccumulationKHRShift = 4, - CooperativeMatrixOperandsMax = 0x7fffffff, -}; - -enum CooperativeMatrixOperandsMask : unsigned { - CooperativeMatrixOperandsMaskNone = 0, - CooperativeMatrixOperandsMatrixASignedComponentsKHRMask = 0x00000001, - CooperativeMatrixOperandsMatrixBSignedComponentsKHRMask = 0x00000002, - CooperativeMatrixOperandsMatrixCSignedComponentsKHRMask = 0x00000004, - CooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask = 0x00000008, - CooperativeMatrixOperandsSaturatingAccumulationKHRMask = 0x00000010, -}; - -enum CooperativeMatrixLayout { - CooperativeMatrixLayoutRowMajorKHR = 0, - CooperativeMatrixLayoutColumnMajorKHR = 1, - CooperativeMatrixLayoutRowBlockedInterleavedARM = 4202, - CooperativeMatrixLayoutColumnBlockedInterleavedARM = 4203, - CooperativeMatrixLayoutMax = 0x7fffffff, -}; - -enum CooperativeMatrixUse { - CooperativeMatrixUseMatrixAKHR = 0, - CooperativeMatrixUseMatrixBKHR = 1, - CooperativeMatrixUseMatrixAccumulatorKHR = 2, - CooperativeMatrixUseMax = 0x7fffffff, -}; - -enum CooperativeMatrixReduceShift { - CooperativeMatrixReduceRowShift = 0, - CooperativeMatrixReduceColumnShift = 1, - CooperativeMatrixReduce2x2Shift = 2, - CooperativeMatrixReduceMax = 0x7fffffff, -}; - -enum CooperativeMatrixReduceMask : unsigned { - CooperativeMatrixReduceMaskNone = 0, - CooperativeMatrixReduceRowMask = 0x00000001, - CooperativeMatrixReduceColumnMask = 0x00000002, - CooperativeMatrixReduce2x2Mask = 0x00000004, -}; - -enum TensorClampMode { - TensorClampModeUndefined = 0, - TensorClampModeConstant = 1, - TensorClampModeClampToEdge = 2, - TensorClampModeRepeat = 3, - TensorClampModeRepeatMirrored = 4, - TensorClampModeMax = 0x7fffffff, -}; - -enum TensorAddressingOperandsShift { - TensorAddressingOperandsTensorViewShift = 0, - TensorAddressingOperandsDecodeFuncShift = 1, - TensorAddressingOperandsMax = 0x7fffffff, -}; - -enum TensorAddressingOperandsMask : unsigned { - TensorAddressingOperandsMaskNone = 0, - TensorAddressingOperandsTensorViewMask = 0x00000001, - TensorAddressingOperandsDecodeFuncMask = 0x00000002, -}; - -enum InitializationModeQualifier { - InitializationModeQualifierInitOnDeviceReprogramINTEL = 0, - InitializationModeQualifierInitOnDeviceResetINTEL = 1, - InitializationModeQualifierMax = 0x7fffffff, -}; - -enum HostAccessQualifier { - HostAccessQualifierNoneINTEL = 0, - HostAccessQualifierReadINTEL = 1, - HostAccessQualifierWriteINTEL = 2, - HostAccessQualifierReadWriteINTEL = 3, - HostAccessQualifierMax = 0x7fffffff, -}; - -enum LoadCacheControl { - LoadCacheControlUncachedINTEL = 0, - LoadCacheControlCachedINTEL = 1, - LoadCacheControlStreamingINTEL = 2, - LoadCacheControlInvalidateAfterReadINTEL = 3, - LoadCacheControlConstCachedINTEL = 4, - LoadCacheControlMax = 0x7fffffff, -}; - -enum StoreCacheControl { - StoreCacheControlUncachedINTEL = 0, - StoreCacheControlWriteThroughINTEL = 1, - StoreCacheControlWriteBackINTEL = 2, - StoreCacheControlStreamingINTEL = 3, - StoreCacheControlMax = 0x7fffffff, -}; - -enum NamedMaximumNumberOfRegisters { - NamedMaximumNumberOfRegistersAutoINTEL = 0, - NamedMaximumNumberOfRegistersMax = 0x7fffffff, -}; - -enum RawAccessChainOperandsShift { - RawAccessChainOperandsRobustnessPerComponentNVShift = 0, - RawAccessChainOperandsRobustnessPerElementNVShift = 1, - RawAccessChainOperandsMax = 0x7fffffff, -}; - -enum RawAccessChainOperandsMask : unsigned { - RawAccessChainOperandsMaskNone = 0, - RawAccessChainOperandsRobustnessPerComponentNVMask = 0x00000001, - RawAccessChainOperandsRobustnessPerElementNVMask = 0x00000002, -}; - -enum FPEncoding { - FPEncodingMax = 0x7fffffff, -}; - -enum Op { - OpNop = 0, - OpUndef = 1, - OpSourceContinued = 2, - OpSource = 3, - OpSourceExtension = 4, - OpName = 5, - OpMemberName = 6, - OpString = 7, - OpLine = 8, - OpExtension = 10, - OpExtInstImport = 11, - OpExtInst = 12, - OpMemoryModel = 14, - OpEntryPoint = 15, - OpExecutionMode = 16, - OpCapability = 17, - OpTypeVoid = 19, - OpTypeBool = 20, - OpTypeInt = 21, - OpTypeFloat = 22, - OpTypeVector = 23, - OpTypeMatrix = 24, - OpTypeImage = 25, - OpTypeSampler = 26, - OpTypeSampledImage = 27, - OpTypeArray = 28, - OpTypeRuntimeArray = 29, - OpTypeStruct = 30, - OpTypeOpaque = 31, - OpTypePointer = 32, - OpTypeFunction = 33, - OpTypeEvent = 34, - OpTypeDeviceEvent = 35, - OpTypeReserveId = 36, - OpTypeQueue = 37, - OpTypePipe = 38, - OpTypeForwardPointer = 39, - OpConstantTrue = 41, - OpConstantFalse = 42, - OpConstant = 43, - OpConstantComposite = 44, - OpConstantSampler = 45, - OpConstantNull = 46, - OpSpecConstantTrue = 48, - OpSpecConstantFalse = 49, - OpSpecConstant = 50, - OpSpecConstantComposite = 51, - OpSpecConstantOp = 52, - OpFunction = 54, - OpFunctionParameter = 55, - OpFunctionEnd = 56, - OpFunctionCall = 57, - OpVariable = 59, - OpImageTexelPointer = 60, - OpLoad = 61, - OpStore = 62, - OpCopyMemory = 63, - OpCopyMemorySized = 64, - OpAccessChain = 65, - OpInBoundsAccessChain = 66, - OpPtrAccessChain = 67, - OpArrayLength = 68, - OpGenericPtrMemSemantics = 69, - OpInBoundsPtrAccessChain = 70, - OpDecorate = 71, - OpMemberDecorate = 72, - OpDecorationGroup = 73, - OpGroupDecorate = 74, - OpGroupMemberDecorate = 75, - OpVectorExtractDynamic = 77, - OpVectorInsertDynamic = 78, - OpVectorShuffle = 79, - OpCompositeConstruct = 80, - OpCompositeExtract = 81, - OpCompositeInsert = 82, - OpCopyObject = 83, - OpTranspose = 84, - OpSampledImage = 86, - OpImageSampleImplicitLod = 87, - OpImageSampleExplicitLod = 88, - OpImageSampleDrefImplicitLod = 89, - OpImageSampleDrefExplicitLod = 90, - OpImageSampleProjImplicitLod = 91, - OpImageSampleProjExplicitLod = 92, - OpImageSampleProjDrefImplicitLod = 93, - OpImageSampleProjDrefExplicitLod = 94, - OpImageFetch = 95, - OpImageGather = 96, - OpImageDrefGather = 97, - OpImageRead = 98, - OpImageWrite = 99, - OpImage = 100, - OpImageQueryFormat = 101, - OpImageQueryOrder = 102, - OpImageQuerySizeLod = 103, - OpImageQuerySize = 104, - OpImageQueryLod = 105, - OpImageQueryLevels = 106, - OpImageQuerySamples = 107, - OpConvertFToU = 109, - OpConvertFToS = 110, - OpConvertSToF = 111, - OpConvertUToF = 112, - OpUConvert = 113, - OpSConvert = 114, - OpFConvert = 115, - OpQuantizeToF16 = 116, - OpConvertPtrToU = 117, - OpSatConvertSToU = 118, - OpSatConvertUToS = 119, - OpConvertUToPtr = 120, - OpPtrCastToGeneric = 121, - OpGenericCastToPtr = 122, - OpGenericCastToPtrExplicit = 123, - OpBitcast = 124, - OpSNegate = 126, - OpFNegate = 127, - OpIAdd = 128, - OpFAdd = 129, - OpISub = 130, - OpFSub = 131, - OpIMul = 132, - OpFMul = 133, - OpUDiv = 134, - OpSDiv = 135, - OpFDiv = 136, - OpUMod = 137, - OpSRem = 138, - OpSMod = 139, - OpFRem = 140, - OpFMod = 141, - OpVectorTimesScalar = 142, - OpMatrixTimesScalar = 143, - OpVectorTimesMatrix = 144, - OpMatrixTimesVector = 145, - OpMatrixTimesMatrix = 146, - OpOuterProduct = 147, - OpDot = 148, - OpIAddCarry = 149, - OpISubBorrow = 150, - OpUMulExtended = 151, - OpSMulExtended = 152, - OpAny = 154, - OpAll = 155, - OpIsNan = 156, - OpIsInf = 157, - OpIsFinite = 158, - OpIsNormal = 159, - OpSignBitSet = 160, - OpLessOrGreater = 161, - OpOrdered = 162, - OpUnordered = 163, - OpLogicalEqual = 164, - OpLogicalNotEqual = 165, - OpLogicalOr = 166, - OpLogicalAnd = 167, - OpLogicalNot = 168, - OpSelect = 169, - OpIEqual = 170, - OpINotEqual = 171, - OpUGreaterThan = 172, - OpSGreaterThan = 173, - OpUGreaterThanEqual = 174, - OpSGreaterThanEqual = 175, - OpULessThan = 176, - OpSLessThan = 177, - OpULessThanEqual = 178, - OpSLessThanEqual = 179, - OpFOrdEqual = 180, - OpFUnordEqual = 181, - OpFOrdNotEqual = 182, - OpFUnordNotEqual = 183, - OpFOrdLessThan = 184, - OpFUnordLessThan = 185, - OpFOrdGreaterThan = 186, - OpFUnordGreaterThan = 187, - OpFOrdLessThanEqual = 188, - OpFUnordLessThanEqual = 189, - OpFOrdGreaterThanEqual = 190, - OpFUnordGreaterThanEqual = 191, - OpShiftRightLogical = 194, - OpShiftRightArithmetic = 195, - OpShiftLeftLogical = 196, - OpBitwiseOr = 197, - OpBitwiseXor = 198, - OpBitwiseAnd = 199, - OpNot = 200, - OpBitFieldInsert = 201, - OpBitFieldSExtract = 202, - OpBitFieldUExtract = 203, - OpBitReverse = 204, - OpBitCount = 205, - OpDPdx = 207, - OpDPdy = 208, - OpFwidth = 209, - OpDPdxFine = 210, - OpDPdyFine = 211, - OpFwidthFine = 212, - OpDPdxCoarse = 213, - OpDPdyCoarse = 214, - OpFwidthCoarse = 215, - OpEmitVertex = 218, - OpEndPrimitive = 219, - OpEmitStreamVertex = 220, - OpEndStreamPrimitive = 221, - OpControlBarrier = 224, - OpMemoryBarrier = 225, - OpAtomicLoad = 227, - OpAtomicStore = 228, - OpAtomicExchange = 229, - OpAtomicCompareExchange = 230, - OpAtomicCompareExchangeWeak = 231, - OpAtomicIIncrement = 232, - OpAtomicIDecrement = 233, - OpAtomicIAdd = 234, - OpAtomicISub = 235, - OpAtomicSMin = 236, - OpAtomicUMin = 237, - OpAtomicSMax = 238, - OpAtomicUMax = 239, - OpAtomicAnd = 240, - OpAtomicOr = 241, - OpAtomicXor = 242, - OpPhi = 245, - OpLoopMerge = 246, - OpSelectionMerge = 247, - OpLabel = 248, - OpBranch = 249, - OpBranchConditional = 250, - OpSwitch = 251, - OpKill = 252, - OpReturn = 253, - OpReturnValue = 254, - OpUnreachable = 255, - OpLifetimeStart = 256, - OpLifetimeStop = 257, - OpGroupAsyncCopy = 259, - OpGroupWaitEvents = 260, - OpGroupAll = 261, - OpGroupAny = 262, - OpGroupBroadcast = 263, - OpGroupIAdd = 264, - OpGroupFAdd = 265, - OpGroupFMin = 266, - OpGroupUMin = 267, - OpGroupSMin = 268, - OpGroupFMax = 269, - OpGroupUMax = 270, - OpGroupSMax = 271, - OpReadPipe = 274, - OpWritePipe = 275, - OpReservedReadPipe = 276, - OpReservedWritePipe = 277, - OpReserveReadPipePackets = 278, - OpReserveWritePipePackets = 279, - OpCommitReadPipe = 280, - OpCommitWritePipe = 281, - OpIsValidReserveId = 282, - OpGetNumPipePackets = 283, - OpGetMaxPipePackets = 284, - OpGroupReserveReadPipePackets = 285, - OpGroupReserveWritePipePackets = 286, - OpGroupCommitReadPipe = 287, - OpGroupCommitWritePipe = 288, - OpEnqueueMarker = 291, - OpEnqueueKernel = 292, - OpGetKernelNDrangeSubGroupCount = 293, - OpGetKernelNDrangeMaxSubGroupSize = 294, - OpGetKernelWorkGroupSize = 295, - OpGetKernelPreferredWorkGroupSizeMultiple = 296, - OpRetainEvent = 297, - OpReleaseEvent = 298, - OpCreateUserEvent = 299, - OpIsValidEvent = 300, - OpSetUserEventStatus = 301, - OpCaptureEventProfilingInfo = 302, - OpGetDefaultQueue = 303, - OpBuildNDRange = 304, - OpImageSparseSampleImplicitLod = 305, - OpImageSparseSampleExplicitLod = 306, - OpImageSparseSampleDrefImplicitLod = 307, - OpImageSparseSampleDrefExplicitLod = 308, - OpImageSparseSampleProjImplicitLod = 309, - OpImageSparseSampleProjExplicitLod = 310, - OpImageSparseSampleProjDrefImplicitLod = 311, - OpImageSparseSampleProjDrefExplicitLod = 312, - OpImageSparseFetch = 313, - OpImageSparseGather = 314, - OpImageSparseDrefGather = 315, - OpImageSparseTexelsResident = 316, - OpNoLine = 317, - OpAtomicFlagTestAndSet = 318, - OpAtomicFlagClear = 319, - OpImageSparseRead = 320, - OpSizeOf = 321, - OpTypePipeStorage = 322, - OpConstantPipeStorage = 323, - OpCreatePipeFromPipeStorage = 324, - OpGetKernelLocalSizeForSubgroupCount = 325, - OpGetKernelMaxNumSubgroups = 326, - OpTypeNamedBarrier = 327, - OpNamedBarrierInitialize = 328, - OpMemoryNamedBarrier = 329, - OpModuleProcessed = 330, - OpExecutionModeId = 331, - OpDecorateId = 332, - OpGroupNonUniformElect = 333, - OpGroupNonUniformAll = 334, - OpGroupNonUniformAny = 335, - OpGroupNonUniformAllEqual = 336, - OpGroupNonUniformBroadcast = 337, - OpGroupNonUniformBroadcastFirst = 338, - OpGroupNonUniformBallot = 339, - OpGroupNonUniformInverseBallot = 340, - OpGroupNonUniformBallotBitExtract = 341, - OpGroupNonUniformBallotBitCount = 342, - OpGroupNonUniformBallotFindLSB = 343, - OpGroupNonUniformBallotFindMSB = 344, - OpGroupNonUniformShuffle = 345, - OpGroupNonUniformShuffleXor = 346, - OpGroupNonUniformShuffleUp = 347, - OpGroupNonUniformShuffleDown = 348, - OpGroupNonUniformIAdd = 349, - OpGroupNonUniformFAdd = 350, - OpGroupNonUniformIMul = 351, - OpGroupNonUniformFMul = 352, - OpGroupNonUniformSMin = 353, - OpGroupNonUniformUMin = 354, - OpGroupNonUniformFMin = 355, - OpGroupNonUniformSMax = 356, - OpGroupNonUniformUMax = 357, - OpGroupNonUniformFMax = 358, - OpGroupNonUniformBitwiseAnd = 359, - OpGroupNonUniformBitwiseOr = 360, - OpGroupNonUniformBitwiseXor = 361, - OpGroupNonUniformLogicalAnd = 362, - OpGroupNonUniformLogicalOr = 363, - OpGroupNonUniformLogicalXor = 364, - OpGroupNonUniformQuadBroadcast = 365, - OpGroupNonUniformQuadSwap = 366, - OpCopyLogical = 400, - OpPtrEqual = 401, - OpPtrNotEqual = 402, - OpPtrDiff = 403, - OpColorAttachmentReadEXT = 4160, - OpDepthAttachmentReadEXT = 4161, - OpStencilAttachmentReadEXT = 4162, - OpTerminateInvocation = 4416, - OpTypeUntypedPointerKHR = 4417, - OpUntypedVariableKHR = 4418, - OpUntypedAccessChainKHR = 4419, - OpUntypedInBoundsAccessChainKHR = 4420, - OpSubgroupBallotKHR = 4421, - OpSubgroupFirstInvocationKHR = 4422, - OpUntypedPtrAccessChainKHR = 4423, - OpUntypedInBoundsPtrAccessChainKHR = 4424, - OpUntypedArrayLengthKHR = 4425, - OpUntypedPrefetchKHR = 4426, - OpSubgroupAllKHR = 4428, - OpSubgroupAnyKHR = 4429, - OpSubgroupAllEqualKHR = 4430, - OpGroupNonUniformRotateKHR = 4431, - OpSubgroupReadInvocationKHR = 4432, - OpExtInstWithForwardRefsKHR = 4433, - OpTraceRayKHR = 4445, - OpExecuteCallableKHR = 4446, - OpConvertUToAccelerationStructureKHR = 4447, - OpIgnoreIntersectionKHR = 4448, - OpTerminateRayKHR = 4449, - OpSDot = 4450, - OpSDotKHR = 4450, - OpUDot = 4451, - OpUDotKHR = 4451, - OpSUDot = 4452, - OpSUDotKHR = 4452, - OpSDotAccSat = 4453, - OpSDotAccSatKHR = 4453, - OpUDotAccSat = 4454, - OpUDotAccSatKHR = 4454, - OpSUDotAccSat = 4455, - OpSUDotAccSatKHR = 4455, - OpTypeCooperativeMatrixKHR = 4456, - OpCooperativeMatrixLoadKHR = 4457, - OpCooperativeMatrixStoreKHR = 4458, - OpCooperativeMatrixMulAddKHR = 4459, - OpCooperativeMatrixLengthKHR = 4460, - OpConstantCompositeReplicateEXT = 4461, - OpSpecConstantCompositeReplicateEXT = 4462, - OpCompositeConstructReplicateEXT = 4463, - OpTypeRayQueryKHR = 4472, - OpRayQueryInitializeKHR = 4473, - OpRayQueryTerminateKHR = 4474, - OpRayQueryGenerateIntersectionKHR = 4475, - OpRayQueryConfirmIntersectionKHR = 4476, - OpRayQueryProceedKHR = 4477, - OpRayQueryGetIntersectionTypeKHR = 4479, - OpImageSampleWeightedQCOM = 4480, - OpImageBoxFilterQCOM = 4481, - OpImageBlockMatchSSDQCOM = 4482, - OpImageBlockMatchSADQCOM = 4483, - OpImageBlockMatchWindowSSDQCOM = 4500, - OpImageBlockMatchWindowSADQCOM = 4501, - OpImageBlockMatchGatherSSDQCOM = 4502, - OpImageBlockMatchGatherSADQCOM = 4503, - OpGroupIAddNonUniformAMD = 5000, - OpGroupFAddNonUniformAMD = 5001, - OpGroupFMinNonUniformAMD = 5002, - OpGroupUMinNonUniformAMD = 5003, - OpGroupSMinNonUniformAMD = 5004, - OpGroupFMaxNonUniformAMD = 5005, - OpGroupUMaxNonUniformAMD = 5006, - OpGroupSMaxNonUniformAMD = 5007, - OpFragmentMaskFetchAMD = 5011, - OpFragmentFetchAMD = 5012, - OpReadClockKHR = 5056, - OpAllocateNodePayloadsAMDX = 5074, - OpEnqueueNodePayloadsAMDX = 5075, - OpTypeNodePayloadArrayAMDX = 5076, - OpFinishWritingNodePayloadAMDX = 5078, - OpNodePayloadArrayLengthAMDX = 5090, - OpIsNodePayloadValidAMDX = 5101, - OpConstantStringAMDX = 5103, - OpSpecConstantStringAMDX = 5104, - OpGroupNonUniformQuadAllKHR = 5110, - OpGroupNonUniformQuadAnyKHR = 5111, - OpHitObjectRecordHitMotionNV = 5249, - OpHitObjectRecordHitWithIndexMotionNV = 5250, - OpHitObjectRecordMissMotionNV = 5251, - OpHitObjectGetWorldToObjectNV = 5252, - OpHitObjectGetObjectToWorldNV = 5253, - OpHitObjectGetObjectRayDirectionNV = 5254, - OpHitObjectGetObjectRayOriginNV = 5255, - OpHitObjectTraceRayMotionNV = 5256, - OpHitObjectGetShaderRecordBufferHandleNV = 5257, - OpHitObjectGetShaderBindingTableRecordIndexNV = 5258, - OpHitObjectRecordEmptyNV = 5259, - OpHitObjectTraceRayNV = 5260, - OpHitObjectRecordHitNV = 5261, - OpHitObjectRecordHitWithIndexNV = 5262, - OpHitObjectRecordMissNV = 5263, - OpHitObjectExecuteShaderNV = 5264, - OpHitObjectGetCurrentTimeNV = 5265, - OpHitObjectGetAttributesNV = 5266, - OpHitObjectGetHitKindNV = 5267, - OpHitObjectGetPrimitiveIndexNV = 5268, - OpHitObjectGetGeometryIndexNV = 5269, - OpHitObjectGetInstanceIdNV = 5270, - OpHitObjectGetInstanceCustomIndexNV = 5271, - OpHitObjectGetWorldRayDirectionNV = 5272, - OpHitObjectGetWorldRayOriginNV = 5273, - OpHitObjectGetRayTMaxNV = 5274, - OpHitObjectGetRayTMinNV = 5275, - OpHitObjectIsEmptyNV = 5276, - OpHitObjectIsHitNV = 5277, - OpHitObjectIsMissNV = 5278, - OpReorderThreadWithHitObjectNV = 5279, - OpReorderThreadWithHintNV = 5280, - OpTypeHitObjectNV = 5281, - OpImageSampleFootprintNV = 5283, - OpCooperativeMatrixConvertNV = 5293, - OpEmitMeshTasksEXT = 5294, - OpSetMeshOutputsEXT = 5295, - OpGroupNonUniformPartitionNV = 5296, - OpWritePackedPrimitiveIndices4x8NV = 5299, - OpFetchMicroTriangleVertexPositionNV = 5300, - OpFetchMicroTriangleVertexBarycentricNV = 5301, - OpReportIntersectionKHR = 5334, - OpReportIntersectionNV = 5334, - OpIgnoreIntersectionNV = 5335, - OpTerminateRayNV = 5336, - OpTraceNV = 5337, - OpTraceMotionNV = 5338, - OpTraceRayMotionNV = 5339, - OpRayQueryGetIntersectionTriangleVertexPositionsKHR = 5340, - OpTypeAccelerationStructureKHR = 5341, - OpTypeAccelerationStructureNV = 5341, - OpExecuteCallableNV = 5344, - OpTypeCooperativeMatrixNV = 5358, - OpCooperativeMatrixLoadNV = 5359, - OpCooperativeMatrixStoreNV = 5360, - OpCooperativeMatrixMulAddNV = 5361, - OpCooperativeMatrixLengthNV = 5362, - OpBeginInvocationInterlockEXT = 5364, - OpEndInvocationInterlockEXT = 5365, - OpCooperativeMatrixReduceNV = 5366, - OpCooperativeMatrixLoadTensorNV = 5367, - OpCooperativeMatrixStoreTensorNV = 5368, - OpCooperativeMatrixPerElementOpNV = 5369, - OpTypeTensorLayoutNV = 5370, - OpTypeTensorViewNV = 5371, - OpCreateTensorLayoutNV = 5372, - OpTensorLayoutSetDimensionNV = 5373, - OpTensorLayoutSetStrideNV = 5374, - OpTensorLayoutSliceNV = 5375, - OpTensorLayoutSetClampValueNV = 5376, - OpCreateTensorViewNV = 5377, - OpTensorViewSetDimensionNV = 5378, - OpTensorViewSetStrideNV = 5379, - OpDemoteToHelperInvocation = 5380, - OpDemoteToHelperInvocationEXT = 5380, - OpIsHelperInvocationEXT = 5381, - OpTensorViewSetClipNV = 5382, - OpTensorLayoutSetBlockSizeNV = 5384, - OpCooperativeMatrixTransposeNV = 5390, - OpConvertUToImageNV = 5391, - OpConvertUToSamplerNV = 5392, - OpConvertImageToUNV = 5393, - OpConvertSamplerToUNV = 5394, - OpConvertUToSampledImageNV = 5395, - OpConvertSampledImageToUNV = 5396, - OpSamplerImageAddressingModeNV = 5397, - OpRawAccessChainNV = 5398, - OpSubgroupShuffleINTEL = 5571, - OpSubgroupShuffleDownINTEL = 5572, - OpSubgroupShuffleUpINTEL = 5573, - OpSubgroupShuffleXorINTEL = 5574, - OpSubgroupBlockReadINTEL = 5575, - OpSubgroupBlockWriteINTEL = 5576, - OpSubgroupImageBlockReadINTEL = 5577, - OpSubgroupImageBlockWriteINTEL = 5578, - OpSubgroupImageMediaBlockReadINTEL = 5580, - OpSubgroupImageMediaBlockWriteINTEL = 5581, - OpUCountLeadingZerosINTEL = 5585, - OpUCountTrailingZerosINTEL = 5586, - OpAbsISubINTEL = 5587, - OpAbsUSubINTEL = 5588, - OpIAddSatINTEL = 5589, - OpUAddSatINTEL = 5590, - OpIAverageINTEL = 5591, - OpUAverageINTEL = 5592, - OpIAverageRoundedINTEL = 5593, - OpUAverageRoundedINTEL = 5594, - OpISubSatINTEL = 5595, - OpUSubSatINTEL = 5596, - OpIMul32x16INTEL = 5597, - OpUMul32x16INTEL = 5598, - OpConstantFunctionPointerINTEL = 5600, - OpFunctionPointerCallINTEL = 5601, - OpAsmTargetINTEL = 5609, - OpAsmINTEL = 5610, - OpAsmCallINTEL = 5611, - OpAtomicFMinEXT = 5614, - OpAtomicFMaxEXT = 5615, - OpAssumeTrueKHR = 5630, - OpExpectKHR = 5631, - OpDecorateString = 5632, - OpDecorateStringGOOGLE = 5632, - OpMemberDecorateString = 5633, - OpMemberDecorateStringGOOGLE = 5633, - OpVmeImageINTEL = 5699, - OpTypeVmeImageINTEL = 5700, - OpTypeAvcImePayloadINTEL = 5701, - OpTypeAvcRefPayloadINTEL = 5702, - OpTypeAvcSicPayloadINTEL = 5703, - OpTypeAvcMcePayloadINTEL = 5704, - OpTypeAvcMceResultINTEL = 5705, - OpTypeAvcImeResultINTEL = 5706, - OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, - OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, - OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, - OpTypeAvcImeDualReferenceStreaminINTEL = 5710, - OpTypeAvcRefResultINTEL = 5711, - OpTypeAvcSicResultINTEL = 5712, - OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, - OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, - OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, - OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, - OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, - OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, - OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, - OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, - OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, - OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, - OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, - OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, - OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, - OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, - OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, - OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, - OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, - OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, - OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, - OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, - OpSubgroupAvcMceConvertToImeResultINTEL = 5733, - OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, - OpSubgroupAvcMceConvertToRefResultINTEL = 5735, - OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, - OpSubgroupAvcMceConvertToSicResultINTEL = 5737, - OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, - OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, - OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, - OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, - OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, - OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, - OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, - OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, - OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, - OpSubgroupAvcImeInitializeINTEL = 5747, - OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, - OpSubgroupAvcImeSetDualReferenceINTEL = 5749, - OpSubgroupAvcImeRefWindowSizeINTEL = 5750, - OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, - OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, - OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, - OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, - OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, - OpSubgroupAvcImeSetWeightedSadINTEL = 5756, - OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, - OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, - OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, - OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, - OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, - OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, - OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, - OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, - OpSubgroupAvcImeConvertToMceResultINTEL = 5765, - OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, - OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, - OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, - OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, - OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, - OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, - OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, - OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, - OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, - OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, - OpSubgroupAvcImeGetBorderReachedINTEL = 5776, - OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, - OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, - OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, - OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, - OpSubgroupAvcFmeInitializeINTEL = 5781, - OpSubgroupAvcBmeInitializeINTEL = 5782, - OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, - OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, - OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, - OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, - OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, - OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, - OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, - OpSubgroupAvcRefConvertToMceResultINTEL = 5790, - OpSubgroupAvcSicInitializeINTEL = 5791, - OpSubgroupAvcSicConfigureSkcINTEL = 5792, - OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, - OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, - OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, - OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, - OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, - OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, - OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, - OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, - OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, - OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, - OpSubgroupAvcSicEvaluateIpeINTEL = 5803, - OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, - OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, - OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, - OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, - OpSubgroupAvcSicConvertToMceResultINTEL = 5808, - OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, - OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, - OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, - OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, - OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, - OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, - OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, - OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, - OpVariableLengthArrayINTEL = 5818, - OpSaveMemoryINTEL = 5819, - OpRestoreMemoryINTEL = 5820, - OpArbitraryFloatSinCosPiINTEL = 5840, - OpArbitraryFloatCastINTEL = 5841, - OpArbitraryFloatCastFromIntINTEL = 5842, - OpArbitraryFloatCastToIntINTEL = 5843, - OpArbitraryFloatAddINTEL = 5846, - OpArbitraryFloatSubINTEL = 5847, - OpArbitraryFloatMulINTEL = 5848, - OpArbitraryFloatDivINTEL = 5849, - OpArbitraryFloatGTINTEL = 5850, - OpArbitraryFloatGEINTEL = 5851, - OpArbitraryFloatLTINTEL = 5852, - OpArbitraryFloatLEINTEL = 5853, - OpArbitraryFloatEQINTEL = 5854, - OpArbitraryFloatRecipINTEL = 5855, - OpArbitraryFloatRSqrtINTEL = 5856, - OpArbitraryFloatCbrtINTEL = 5857, - OpArbitraryFloatHypotINTEL = 5858, - OpArbitraryFloatSqrtINTEL = 5859, - OpArbitraryFloatLogINTEL = 5860, - OpArbitraryFloatLog2INTEL = 5861, - OpArbitraryFloatLog10INTEL = 5862, - OpArbitraryFloatLog1pINTEL = 5863, - OpArbitraryFloatExpINTEL = 5864, - OpArbitraryFloatExp2INTEL = 5865, - OpArbitraryFloatExp10INTEL = 5866, - OpArbitraryFloatExpm1INTEL = 5867, - OpArbitraryFloatSinINTEL = 5868, - OpArbitraryFloatCosINTEL = 5869, - OpArbitraryFloatSinCosINTEL = 5870, - OpArbitraryFloatSinPiINTEL = 5871, - OpArbitraryFloatCosPiINTEL = 5872, - OpArbitraryFloatASinINTEL = 5873, - OpArbitraryFloatASinPiINTEL = 5874, - OpArbitraryFloatACosINTEL = 5875, - OpArbitraryFloatACosPiINTEL = 5876, - OpArbitraryFloatATanINTEL = 5877, - OpArbitraryFloatATanPiINTEL = 5878, - OpArbitraryFloatATan2INTEL = 5879, - OpArbitraryFloatPowINTEL = 5880, - OpArbitraryFloatPowRINTEL = 5881, - OpArbitraryFloatPowNINTEL = 5882, - OpLoopControlINTEL = 5887, - OpAliasDomainDeclINTEL = 5911, - OpAliasScopeDeclINTEL = 5912, - OpAliasScopeListDeclINTEL = 5913, - OpFixedSqrtINTEL = 5923, - OpFixedRecipINTEL = 5924, - OpFixedRsqrtINTEL = 5925, - OpFixedSinINTEL = 5926, - OpFixedCosINTEL = 5927, - OpFixedSinCosINTEL = 5928, - OpFixedSinPiINTEL = 5929, - OpFixedCosPiINTEL = 5930, - OpFixedSinCosPiINTEL = 5931, - OpFixedLogINTEL = 5932, - OpFixedExpINTEL = 5933, - OpPtrCastToCrossWorkgroupINTEL = 5934, - OpCrossWorkgroupCastToPtrINTEL = 5938, - OpReadPipeBlockingINTEL = 5946, - OpWritePipeBlockingINTEL = 5947, - OpFPGARegINTEL = 5949, - OpRayQueryGetRayTMinKHR = 6016, - OpRayQueryGetRayFlagsKHR = 6017, - OpRayQueryGetIntersectionTKHR = 6018, - OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, - OpRayQueryGetIntersectionInstanceIdKHR = 6020, - OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, - OpRayQueryGetIntersectionGeometryIndexKHR = 6022, - OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, - OpRayQueryGetIntersectionBarycentricsKHR = 6024, - OpRayQueryGetIntersectionFrontFaceKHR = 6025, - OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, - OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, - OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, - OpRayQueryGetWorldRayDirectionKHR = 6029, - OpRayQueryGetWorldRayOriginKHR = 6030, - OpRayQueryGetIntersectionObjectToWorldKHR = 6031, - OpRayQueryGetIntersectionWorldToObjectKHR = 6032, - OpAtomicFAddEXT = 6035, - OpTypeBufferSurfaceINTEL = 6086, - OpTypeStructContinuedINTEL = 6090, - OpConstantCompositeContinuedINTEL = 6091, - OpSpecConstantCompositeContinuedINTEL = 6092, - OpCompositeConstructContinuedINTEL = 6096, - OpConvertFToBF16INTEL = 6116, - OpConvertBF16ToFINTEL = 6117, - OpControlBarrierArriveINTEL = 6142, - OpControlBarrierWaitINTEL = 6143, - OpArithmeticFenceEXT = 6145, - OpSubgroupBlockPrefetchINTEL = 6221, - OpGroupIMulKHR = 6401, - OpGroupFMulKHR = 6402, - OpGroupBitwiseAndKHR = 6403, - OpGroupBitwiseOrKHR = 6404, - OpGroupBitwiseXorKHR = 6405, - OpGroupLogicalAndKHR = 6406, - OpGroupLogicalOrKHR = 6407, - OpGroupLogicalXorKHR = 6408, - OpMaskedGatherINTEL = 6428, - OpMaskedScatterINTEL = 6429, - OpMax = 0x7fffffff, -}; - -#ifdef SPV_ENABLE_UTILITY_CODE -#ifndef __cplusplus -#include -#endif -inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { - *hasResult = *hasResultType = false; - switch (opcode) { - default: /* unknown opcode */ break; - case OpNop: *hasResult = false; *hasResultType = false; break; - case OpUndef: *hasResult = true; *hasResultType = true; break; - case OpSourceContinued: *hasResult = false; *hasResultType = false; break; - case OpSource: *hasResult = false; *hasResultType = false; break; - case OpSourceExtension: *hasResult = false; *hasResultType = false; break; - case OpName: *hasResult = false; *hasResultType = false; break; - case OpMemberName: *hasResult = false; *hasResultType = false; break; - case OpString: *hasResult = true; *hasResultType = false; break; - case OpLine: *hasResult = false; *hasResultType = false; break; - case OpExtension: *hasResult = false; *hasResultType = false; break; - case OpExtInstImport: *hasResult = true; *hasResultType = false; break; - case OpExtInst: *hasResult = true; *hasResultType = true; break; - case OpMemoryModel: *hasResult = false; *hasResultType = false; break; - case OpEntryPoint: *hasResult = false; *hasResultType = false; break; - case OpExecutionMode: *hasResult = false; *hasResultType = false; break; - case OpCapability: *hasResult = false; *hasResultType = false; break; - case OpTypeVoid: *hasResult = true; *hasResultType = false; break; - case OpTypeBool: *hasResult = true; *hasResultType = false; break; - case OpTypeInt: *hasResult = true; *hasResultType = false; break; - case OpTypeFloat: *hasResult = true; *hasResultType = false; break; - case OpTypeVector: *hasResult = true; *hasResultType = false; break; - case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; - case OpTypeImage: *hasResult = true; *hasResultType = false; break; - case OpTypeSampler: *hasResult = true; *hasResultType = false; break; - case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; - case OpTypeArray: *hasResult = true; *hasResultType = false; break; - case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; - case OpTypeStruct: *hasResult = true; *hasResultType = false; break; - case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; - case OpTypePointer: *hasResult = true; *hasResultType = false; break; - case OpTypeFunction: *hasResult = true; *hasResultType = false; break; - case OpTypeEvent: *hasResult = true; *hasResultType = false; break; - case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; - case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; - case OpTypeQueue: *hasResult = true; *hasResultType = false; break; - case OpTypePipe: *hasResult = true; *hasResultType = false; break; - case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; - case OpConstantTrue: *hasResult = true; *hasResultType = true; break; - case OpConstantFalse: *hasResult = true; *hasResultType = true; break; - case OpConstant: *hasResult = true; *hasResultType = true; break; - case OpConstantComposite: *hasResult = true; *hasResultType = true; break; - case OpConstantSampler: *hasResult = true; *hasResultType = true; break; - case OpConstantNull: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; - case OpSpecConstant: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; - case OpFunction: *hasResult = true; *hasResultType = true; break; - case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; - case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; - case OpFunctionCall: *hasResult = true; *hasResultType = true; break; - case OpVariable: *hasResult = true; *hasResultType = true; break; - case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; - case OpLoad: *hasResult = true; *hasResultType = true; break; - case OpStore: *hasResult = false; *hasResultType = false; break; - case OpCopyMemory: *hasResult = false; *hasResultType = false; break; - case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; - case OpAccessChain: *hasResult = true; *hasResultType = true; break; - case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; - case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; - case OpArrayLength: *hasResult = true; *hasResultType = true; break; - case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; - case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; - case OpDecorate: *hasResult = false; *hasResultType = false; break; - case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; - case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; - case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; - case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; - case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; - case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; - case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; - case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; - case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; - case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; - case OpCopyObject: *hasResult = true; *hasResultType = true; break; - case OpTranspose: *hasResult = true; *hasResultType = true; break; - case OpSampledImage: *hasResult = true; *hasResultType = true; break; - case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageFetch: *hasResult = true; *hasResultType = true; break; - case OpImageGather: *hasResult = true; *hasResultType = true; break; - case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; - case OpImageRead: *hasResult = true; *hasResultType = true; break; - case OpImageWrite: *hasResult = false; *hasResultType = false; break; - case OpImage: *hasResult = true; *hasResultType = true; break; - case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; - case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; - case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; - case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; - case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; - case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; - case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; - case OpConvertFToU: *hasResult = true; *hasResultType = true; break; - case OpConvertFToS: *hasResult = true; *hasResultType = true; break; - case OpConvertSToF: *hasResult = true; *hasResultType = true; break; - case OpConvertUToF: *hasResult = true; *hasResultType = true; break; - case OpUConvert: *hasResult = true; *hasResultType = true; break; - case OpSConvert: *hasResult = true; *hasResultType = true; break; - case OpFConvert: *hasResult = true; *hasResultType = true; break; - case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; - case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; - case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; - case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; - case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; - case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; - case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; - case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; - case OpBitcast: *hasResult = true; *hasResultType = true; break; - case OpSNegate: *hasResult = true; *hasResultType = true; break; - case OpFNegate: *hasResult = true; *hasResultType = true; break; - case OpIAdd: *hasResult = true; *hasResultType = true; break; - case OpFAdd: *hasResult = true; *hasResultType = true; break; - case OpISub: *hasResult = true; *hasResultType = true; break; - case OpFSub: *hasResult = true; *hasResultType = true; break; - case OpIMul: *hasResult = true; *hasResultType = true; break; - case OpFMul: *hasResult = true; *hasResultType = true; break; - case OpUDiv: *hasResult = true; *hasResultType = true; break; - case OpSDiv: *hasResult = true; *hasResultType = true; break; - case OpFDiv: *hasResult = true; *hasResultType = true; break; - case OpUMod: *hasResult = true; *hasResultType = true; break; - case OpSRem: *hasResult = true; *hasResultType = true; break; - case OpSMod: *hasResult = true; *hasResultType = true; break; - case OpFRem: *hasResult = true; *hasResultType = true; break; - case OpFMod: *hasResult = true; *hasResultType = true; break; - case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; - case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; - case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; - case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; - case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; - case OpOuterProduct: *hasResult = true; *hasResultType = true; break; - case OpDot: *hasResult = true; *hasResultType = true; break; - case OpIAddCarry: *hasResult = true; *hasResultType = true; break; - case OpISubBorrow: *hasResult = true; *hasResultType = true; break; - case OpUMulExtended: *hasResult = true; *hasResultType = true; break; - case OpSMulExtended: *hasResult = true; *hasResultType = true; break; - case OpAny: *hasResult = true; *hasResultType = true; break; - case OpAll: *hasResult = true; *hasResultType = true; break; - case OpIsNan: *hasResult = true; *hasResultType = true; break; - case OpIsInf: *hasResult = true; *hasResultType = true; break; - case OpIsFinite: *hasResult = true; *hasResultType = true; break; - case OpIsNormal: *hasResult = true; *hasResultType = true; break; - case OpSignBitSet: *hasResult = true; *hasResultType = true; break; - case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; - case OpOrdered: *hasResult = true; *hasResultType = true; break; - case OpUnordered: *hasResult = true; *hasResultType = true; break; - case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; - case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; - case OpLogicalOr: *hasResult = true; *hasResultType = true; break; - case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; - case OpLogicalNot: *hasResult = true; *hasResultType = true; break; - case OpSelect: *hasResult = true; *hasResultType = true; break; - case OpIEqual: *hasResult = true; *hasResultType = true; break; - case OpINotEqual: *hasResult = true; *hasResultType = true; break; - case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpULessThan: *hasResult = true; *hasResultType = true; break; - case OpSLessThan: *hasResult = true; *hasResultType = true; break; - case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; - case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; - case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; - case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; - case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; - case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; - case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; - case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; - case OpNot: *hasResult = true; *hasResultType = true; break; - case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; - case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; - case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; - case OpBitReverse: *hasResult = true; *hasResultType = true; break; - case OpBitCount: *hasResult = true; *hasResultType = true; break; - case OpDPdx: *hasResult = true; *hasResultType = true; break; - case OpDPdy: *hasResult = true; *hasResultType = true; break; - case OpFwidth: *hasResult = true; *hasResultType = true; break; - case OpDPdxFine: *hasResult = true; *hasResultType = true; break; - case OpDPdyFine: *hasResult = true; *hasResultType = true; break; - case OpFwidthFine: *hasResult = true; *hasResultType = true; break; - case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; - case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; - case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; - case OpEmitVertex: *hasResult = false; *hasResultType = false; break; - case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; - case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; - case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; - case OpControlBarrier: *hasResult = false; *hasResultType = false; break; - case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; - case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; - case OpAtomicStore: *hasResult = false; *hasResultType = false; break; - case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; - case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; - case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; - case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; - case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; - case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; - case OpAtomicISub: *hasResult = true; *hasResultType = true; break; - case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; - case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; - case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; - case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; - case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; - case OpAtomicOr: *hasResult = true; *hasResultType = true; break; - case OpAtomicXor: *hasResult = true; *hasResultType = true; break; - case OpPhi: *hasResult = true; *hasResultType = true; break; - case OpLoopMerge: *hasResult = false; *hasResultType = false; break; - case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; - case OpLabel: *hasResult = true; *hasResultType = false; break; - case OpBranch: *hasResult = false; *hasResultType = false; break; - case OpBranchConditional: *hasResult = false; *hasResultType = false; break; - case OpSwitch: *hasResult = false; *hasResultType = false; break; - case OpKill: *hasResult = false; *hasResultType = false; break; - case OpReturn: *hasResult = false; *hasResultType = false; break; - case OpReturnValue: *hasResult = false; *hasResultType = false; break; - case OpUnreachable: *hasResult = false; *hasResultType = false; break; - case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; - case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; - case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; - case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; - case OpGroupAll: *hasResult = true; *hasResultType = true; break; - case OpGroupAny: *hasResult = true; *hasResultType = true; break; - case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; - case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupFMin: *hasResult = true; *hasResultType = true; break; - case OpGroupUMin: *hasResult = true; *hasResultType = true; break; - case OpGroupSMin: *hasResult = true; *hasResultType = true; break; - case OpGroupFMax: *hasResult = true; *hasResultType = true; break; - case OpGroupUMax: *hasResult = true; *hasResultType = true; break; - case OpGroupSMax: *hasResult = true; *hasResultType = true; break; - case OpReadPipe: *hasResult = true; *hasResultType = true; break; - case OpWritePipe: *hasResult = true; *hasResultType = true; break; - case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; - case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; - case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; - case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; - case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; - case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; - case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; - case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; - case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; - case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; - case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; - case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; - case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; - case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; - case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; - case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; - case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; - case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; - case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; - case OpRetainEvent: *hasResult = false; *hasResultType = false; break; - case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; - case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; - case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; - case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; - case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; - case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; - case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; - case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; - case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; - case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; - case OpNoLine: *hasResult = false; *hasResultType = false; break; - case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; - case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; - case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; - case OpSizeOf: *hasResult = true; *hasResultType = true; break; - case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; - case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; - case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; - case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; - case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; - case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; - case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; - case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; - case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; - case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; - case OpDecorateId: *hasResult = false; *hasResultType = false; break; - case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; - case OpCopyLogical: *hasResult = true; *hasResultType = true; break; - case OpPtrEqual: *hasResult = true; *hasResultType = true; break; - case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; - case OpPtrDiff: *hasResult = true; *hasResultType = true; break; - case OpColorAttachmentReadEXT: *hasResult = true; *hasResultType = true; break; - case OpDepthAttachmentReadEXT: *hasResult = true; *hasResultType = true; break; - case OpStencilAttachmentReadEXT: *hasResult = true; *hasResultType = true; break; - case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break; - case OpTypeUntypedPointerKHR: *hasResult = true; *hasResultType = false; break; - case OpUntypedVariableKHR: *hasResult = true; *hasResultType = true; break; - case OpUntypedAccessChainKHR: *hasResult = true; *hasResultType = true; break; - case OpUntypedInBoundsAccessChainKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; - case OpUntypedPtrAccessChainKHR: *hasResult = true; *hasResultType = true; break; - case OpUntypedInBoundsPtrAccessChainKHR: *hasResult = true; *hasResultType = true; break; - case OpUntypedArrayLengthKHR: *hasResult = true; *hasResultType = true; break; - case OpUntypedPrefetchKHR: *hasResult = false; *hasResultType = false; break; - case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; - case OpExtInstWithForwardRefsKHR: *hasResult = true; *hasResultType = true; break; - case OpTraceRayKHR: *hasResult = false; *hasResultType = false; break; - case OpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break; - case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break; - case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break; - case OpSDot: *hasResult = true; *hasResultType = true; break; - case OpUDot: *hasResult = true; *hasResultType = true; break; - case OpSUDot: *hasResult = true; *hasResultType = true; break; - case OpSDotAccSat: *hasResult = true; *hasResultType = true; break; - case OpUDotAccSat: *hasResult = true; *hasResultType = true; break; - case OpSUDotAccSat: *hasResult = true; *hasResultType = true; break; - case OpTypeCooperativeMatrixKHR: *hasResult = true; *hasResultType = false; break; - case OpCooperativeMatrixLoadKHR: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixStoreKHR: *hasResult = false; *hasResultType = false; break; - case OpCooperativeMatrixMulAddKHR: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixLengthKHR: *hasResult = true; *hasResultType = true; break; - case OpConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break; - case OpCompositeConstructReplicateEXT: *hasResult = true; *hasResultType = true; break; - case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break; - case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; - case OpImageSampleWeightedQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBoxFilterQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchSSDQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchSADQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchWindowSSDQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchWindowSADQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchGatherSSDQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchGatherSADQCOM: *hasResult = true; *hasResultType = true; break; - case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; - case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; - case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; - case OpAllocateNodePayloadsAMDX: *hasResult = true; *hasResultType = true; break; - case OpEnqueueNodePayloadsAMDX: *hasResult = false; *hasResultType = false; break; - case OpTypeNodePayloadArrayAMDX: *hasResult = true; *hasResultType = false; break; - case OpFinishWritingNodePayloadAMDX: *hasResult = true; *hasResultType = true; break; - case OpNodePayloadArrayLengthAMDX: *hasResult = true; *hasResultType = true; break; - case OpIsNodePayloadValidAMDX: *hasResult = true; *hasResultType = true; break; - case OpConstantStringAMDX: *hasResult = true; *hasResultType = false; break; - case OpSpecConstantStringAMDX: *hasResult = true; *hasResultType = false; break; - case OpGroupNonUniformQuadAllKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformQuadAnyKHR: *hasResult = true; *hasResultType = true; break; - case OpHitObjectRecordHitMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordHitWithIndexMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordMissMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetWorldToObjectNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetObjectToWorldNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetObjectRayDirectionNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetObjectRayOriginNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectTraceRayMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetShaderRecordBufferHandleNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetShaderBindingTableRecordIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectRecordEmptyNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectTraceRayNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordHitNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordHitWithIndexNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordMissNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectExecuteShaderNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetCurrentTimeNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetAttributesNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetHitKindNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetPrimitiveIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetGeometryIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetInstanceIdNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetInstanceCustomIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetWorldRayDirectionNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetWorldRayOriginNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetRayTMaxNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetRayTMinNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectIsEmptyNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectIsHitNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectIsMissNV: *hasResult = true; *hasResultType = true; break; - case OpReorderThreadWithHitObjectNV: *hasResult = false; *hasResultType = false; break; - case OpReorderThreadWithHintNV: *hasResult = false; *hasResultType = false; break; - case OpTypeHitObjectNV: *hasResult = true; *hasResultType = false; break; - case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixConvertNV: *hasResult = true; *hasResultType = true; break; - case OpEmitMeshTasksEXT: *hasResult = false; *hasResultType = false; break; - case OpSetMeshOutputsEXT: *hasResult = false; *hasResultType = false; break; - case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; - case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; - case OpFetchMicroTriangleVertexPositionNV: *hasResult = true; *hasResultType = true; break; - case OpFetchMicroTriangleVertexBarycentricNV: *hasResult = true; *hasResultType = true; break; - case OpReportIntersectionKHR: *hasResult = true; *hasResultType = true; break; - case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; - case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; - case OpTraceNV: *hasResult = false; *hasResultType = false; break; - case OpTraceMotionNV: *hasResult = false; *hasResultType = false; break; - case OpTraceRayMotionNV: *hasResult = false; *hasResultType = false; break; - case OpRayQueryGetIntersectionTriangleVertexPositionsKHR: *hasResult = true; *hasResultType = true; break; - case OpTypeAccelerationStructureKHR: *hasResult = true; *hasResultType = false; break; - case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; - case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; - case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; - case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; - case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; - case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; - case OpCooperativeMatrixReduceNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixLoadTensorNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixStoreTensorNV: *hasResult = false; *hasResultType = false; break; - case OpCooperativeMatrixPerElementOpNV: *hasResult = true; *hasResultType = true; break; - case OpTypeTensorLayoutNV: *hasResult = true; *hasResultType = false; break; - case OpTypeTensorViewNV: *hasResult = true; *hasResultType = false; break; - case OpCreateTensorLayoutNV: *hasResult = true; *hasResultType = true; break; - case OpTensorLayoutSetDimensionNV: *hasResult = true; *hasResultType = true; break; - case OpTensorLayoutSetStrideNV: *hasResult = true; *hasResultType = true; break; - case OpTensorLayoutSliceNV: *hasResult = true; *hasResultType = true; break; - case OpTensorLayoutSetClampValueNV: *hasResult = true; *hasResultType = true; break; - case OpCreateTensorViewNV: *hasResult = true; *hasResultType = true; break; - case OpTensorViewSetDimensionNV: *hasResult = true; *hasResultType = true; break; - case OpTensorViewSetStrideNV: *hasResult = true; *hasResultType = true; break; - case OpDemoteToHelperInvocation: *hasResult = false; *hasResultType = false; break; - case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; - case OpTensorViewSetClipNV: *hasResult = true; *hasResultType = true; break; - case OpTensorLayoutSetBlockSizeNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixTransposeNV: *hasResult = true; *hasResultType = true; break; - case OpConvertUToImageNV: *hasResult = true; *hasResultType = true; break; - case OpConvertUToSamplerNV: *hasResult = true; *hasResultType = true; break; - case OpConvertImageToUNV: *hasResult = true; *hasResultType = true; break; - case OpConvertSamplerToUNV: *hasResult = true; *hasResultType = true; break; - case OpConvertUToSampledImageNV: *hasResult = true; *hasResultType = true; break; - case OpConvertSampledImageToUNV: *hasResult = true; *hasResultType = true; break; - case OpSamplerImageAddressingModeNV: *hasResult = false; *hasResultType = false; break; - case OpRawAccessChainNV: *hasResult = true; *hasResultType = true; break; - case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; - case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; - case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; - case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; - case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; - case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; - case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; - case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; - case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; - case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; - case OpConstantFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break; - case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break; - case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break; - case OpAsmINTEL: *hasResult = true; *hasResultType = true; break; - case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break; - case OpAtomicFMinEXT: *hasResult = true; *hasResultType = true; break; - case OpAtomicFMaxEXT: *hasResult = true; *hasResultType = true; break; - case OpAssumeTrueKHR: *hasResult = false; *hasResultType = false; break; - case OpExpectKHR: *hasResult = true; *hasResultType = true; break; - case OpDecorateString: *hasResult = false; *hasResultType = false; break; - case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; - case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; - case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; - case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break; - case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break; - case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break; - case OpArbitraryFloatSinCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCastINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCastFromIntINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCastToIntINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatAddINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSubINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatMulINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatDivINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatGTINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatGEINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLTINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLEINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatEQINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatRecipINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatRSqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCbrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatHypotINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLogINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLog2INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLog10INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLog1pINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExpINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExp2INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExp10INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExpm1INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSinINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSinCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSinPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatASinINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatASinPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatACosINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatACosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatATanINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatATanPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatATan2INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatPowINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break; - case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break; - case OpAliasDomainDeclINTEL: *hasResult = true; *hasResultType = false; break; - case OpAliasScopeDeclINTEL: *hasResult = true; *hasResultType = false; break; - case OpAliasScopeListDeclINTEL: *hasResult = true; *hasResultType = false; break; - case OpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedLogINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedExpINTEL: *hasResult = true; *hasResultType = true; break; - case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break; - case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break; - case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; - case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; - case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; - case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break; - case OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break; - case OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; - case OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; - case OpCompositeConstructContinuedINTEL: *hasResult = true; *hasResultType = true; break; - case OpConvertFToBF16INTEL: *hasResult = true; *hasResultType = true; break; - case OpConvertBF16ToFINTEL: *hasResult = true; *hasResultType = true; break; - case OpControlBarrierArriveINTEL: *hasResult = false; *hasResultType = false; break; - case OpControlBarrierWaitINTEL: *hasResult = false; *hasResultType = false; break; - case OpArithmeticFenceEXT: *hasResult = true; *hasResultType = true; break; - case OpSubgroupBlockPrefetchINTEL: *hasResult = false; *hasResultType = false; break; - case OpGroupIMulKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupFMulKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupBitwiseAndKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupBitwiseOrKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupBitwiseXorKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupLogicalAndKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupLogicalOrKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupLogicalXorKHR: *hasResult = true; *hasResultType = true; break; - case OpMaskedGatherINTEL: *hasResult = true; *hasResultType = true; break; - case OpMaskedScatterINTEL: *hasResult = false; *hasResultType = false; break; - } -} -inline const char* SourceLanguageToString(SourceLanguage value) { - switch (value) { - case SourceLanguageUnknown: return "Unknown"; - case SourceLanguageESSL: return "ESSL"; - case SourceLanguageGLSL: return "GLSL"; - case SourceLanguageOpenCL_C: return "OpenCL_C"; - case SourceLanguageOpenCL_CPP: return "OpenCL_CPP"; - case SourceLanguageHLSL: return "HLSL"; - case SourceLanguageCPP_for_OpenCL: return "CPP_for_OpenCL"; - case SourceLanguageSYCL: return "SYCL"; - case SourceLanguageHERO_C: return "HERO_C"; - case SourceLanguageNZSL: return "NZSL"; - case SourceLanguageWGSL: return "WGSL"; - case SourceLanguageSlang: return "Slang"; - case SourceLanguageZig: return "Zig"; - default: return "Unknown"; - } -} - -inline const char* ExecutionModelToString(ExecutionModel value) { - switch (value) { - case ExecutionModelVertex: return "Vertex"; - case ExecutionModelTessellationControl: return "TessellationControl"; - case ExecutionModelTessellationEvaluation: return "TessellationEvaluation"; - case ExecutionModelGeometry: return "Geometry"; - case ExecutionModelFragment: return "Fragment"; - case ExecutionModelGLCompute: return "GLCompute"; - case ExecutionModelKernel: return "Kernel"; - case ExecutionModelTaskNV: return "TaskNV"; - case ExecutionModelMeshNV: return "MeshNV"; - case ExecutionModelRayGenerationKHR: return "RayGenerationKHR"; - case ExecutionModelIntersectionKHR: return "IntersectionKHR"; - case ExecutionModelAnyHitKHR: return "AnyHitKHR"; - case ExecutionModelClosestHitKHR: return "ClosestHitKHR"; - case ExecutionModelMissKHR: return "MissKHR"; - case ExecutionModelCallableKHR: return "CallableKHR"; - case ExecutionModelTaskEXT: return "TaskEXT"; - case ExecutionModelMeshEXT: return "MeshEXT"; - default: return "Unknown"; - } -} - -inline const char* AddressingModelToString(AddressingModel value) { - switch (value) { - case AddressingModelLogical: return "Logical"; - case AddressingModelPhysical32: return "Physical32"; - case AddressingModelPhysical64: return "Physical64"; - case AddressingModelPhysicalStorageBuffer64: return "PhysicalStorageBuffer64"; - default: return "Unknown"; - } -} - -inline const char* MemoryModelToString(MemoryModel value) { - switch (value) { - case MemoryModelSimple: return "Simple"; - case MemoryModelGLSL450: return "GLSL450"; - case MemoryModelOpenCL: return "OpenCL"; - case MemoryModelVulkan: return "Vulkan"; - default: return "Unknown"; - } -} - -inline const char* ExecutionModeToString(ExecutionMode value) { - switch (value) { - case ExecutionModeInvocations: return "Invocations"; - case ExecutionModeSpacingEqual: return "SpacingEqual"; - case ExecutionModeSpacingFractionalEven: return "SpacingFractionalEven"; - case ExecutionModeSpacingFractionalOdd: return "SpacingFractionalOdd"; - case ExecutionModeVertexOrderCw: return "VertexOrderCw"; - case ExecutionModeVertexOrderCcw: return "VertexOrderCcw"; - case ExecutionModePixelCenterInteger: return "PixelCenterInteger"; - case ExecutionModeOriginUpperLeft: return "OriginUpperLeft"; - case ExecutionModeOriginLowerLeft: return "OriginLowerLeft"; - case ExecutionModeEarlyFragmentTests: return "EarlyFragmentTests"; - case ExecutionModePointMode: return "PointMode"; - case ExecutionModeXfb: return "Xfb"; - case ExecutionModeDepthReplacing: return "DepthReplacing"; - case ExecutionModeDepthGreater: return "DepthGreater"; - case ExecutionModeDepthLess: return "DepthLess"; - case ExecutionModeDepthUnchanged: return "DepthUnchanged"; - case ExecutionModeLocalSize: return "LocalSize"; - case ExecutionModeLocalSizeHint: return "LocalSizeHint"; - case ExecutionModeInputPoints: return "InputPoints"; - case ExecutionModeInputLines: return "InputLines"; - case ExecutionModeInputLinesAdjacency: return "InputLinesAdjacency"; - case ExecutionModeTriangles: return "Triangles"; - case ExecutionModeInputTrianglesAdjacency: return "InputTrianglesAdjacency"; - case ExecutionModeQuads: return "Quads"; - case ExecutionModeIsolines: return "Isolines"; - case ExecutionModeOutputVertices: return "OutputVertices"; - case ExecutionModeOutputPoints: return "OutputPoints"; - case ExecutionModeOutputLineStrip: return "OutputLineStrip"; - case ExecutionModeOutputTriangleStrip: return "OutputTriangleStrip"; - case ExecutionModeVecTypeHint: return "VecTypeHint"; - case ExecutionModeContractionOff: return "ContractionOff"; - case ExecutionModeInitializer: return "Initializer"; - case ExecutionModeFinalizer: return "Finalizer"; - case ExecutionModeSubgroupSize: return "SubgroupSize"; - case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup"; - case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId"; - case ExecutionModeLocalSizeId: return "LocalSizeId"; - case ExecutionModeLocalSizeHintId: return "LocalSizeHintId"; - case ExecutionModeNonCoherentColorAttachmentReadEXT: return "NonCoherentColorAttachmentReadEXT"; - case ExecutionModeNonCoherentDepthAttachmentReadEXT: return "NonCoherentDepthAttachmentReadEXT"; - case ExecutionModeNonCoherentStencilAttachmentReadEXT: return "NonCoherentStencilAttachmentReadEXT"; - case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlowKHR"; - case ExecutionModePostDepthCoverage: return "PostDepthCoverage"; - case ExecutionModeDenormPreserve: return "DenormPreserve"; - case ExecutionModeDenormFlushToZero: return "DenormFlushToZero"; - case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; - case ExecutionModeRoundingModeRTE: return "RoundingModeRTE"; - case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ"; - case ExecutionModeEarlyAndLateFragmentTestsAMD: return "EarlyAndLateFragmentTestsAMD"; - case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT"; - case ExecutionModeCoalescingAMDX: return "CoalescingAMDX"; - case ExecutionModeIsApiEntryAMDX: return "IsApiEntryAMDX"; - case ExecutionModeMaxNodeRecursionAMDX: return "MaxNodeRecursionAMDX"; - case ExecutionModeStaticNumWorkgroupsAMDX: return "StaticNumWorkgroupsAMDX"; - case ExecutionModeShaderIndexAMDX: return "ShaderIndexAMDX"; - case ExecutionModeMaxNumWorkgroupsAMDX: return "MaxNumWorkgroupsAMDX"; - case ExecutionModeStencilRefUnchangedFrontAMD: return "StencilRefUnchangedFrontAMD"; - case ExecutionModeStencilRefGreaterFrontAMD: return "StencilRefGreaterFrontAMD"; - case ExecutionModeStencilRefLessFrontAMD: return "StencilRefLessFrontAMD"; - case ExecutionModeStencilRefUnchangedBackAMD: return "StencilRefUnchangedBackAMD"; - case ExecutionModeStencilRefGreaterBackAMD: return "StencilRefGreaterBackAMD"; - case ExecutionModeStencilRefLessBackAMD: return "StencilRefLessBackAMD"; - case ExecutionModeQuadDerivativesKHR: return "QuadDerivativesKHR"; - case ExecutionModeRequireFullQuadsKHR: return "RequireFullQuadsKHR"; - case ExecutionModeSharesInputWithAMDX: return "SharesInputWithAMDX"; - case ExecutionModeOutputLinesEXT: return "OutputLinesEXT"; - case ExecutionModeOutputPrimitivesEXT: return "OutputPrimitivesEXT"; - case ExecutionModeDerivativeGroupQuadsKHR: return "DerivativeGroupQuadsKHR"; - case ExecutionModeDerivativeGroupLinearKHR: return "DerivativeGroupLinearKHR"; - case ExecutionModeOutputTrianglesEXT: return "OutputTrianglesEXT"; - case ExecutionModePixelInterlockOrderedEXT: return "PixelInterlockOrderedEXT"; - case ExecutionModePixelInterlockUnorderedEXT: return "PixelInterlockUnorderedEXT"; - case ExecutionModeSampleInterlockOrderedEXT: return "SampleInterlockOrderedEXT"; - case ExecutionModeSampleInterlockUnorderedEXT: return "SampleInterlockUnorderedEXT"; - case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT"; - case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT"; - case ExecutionModeSharedLocalMemorySizeINTEL: return "SharedLocalMemorySizeINTEL"; - case ExecutionModeRoundingModeRTPINTEL: return "RoundingModeRTPINTEL"; - case ExecutionModeRoundingModeRTNINTEL: return "RoundingModeRTNINTEL"; - case ExecutionModeFloatingPointModeALTINTEL: return "FloatingPointModeALTINTEL"; - case ExecutionModeFloatingPointModeIEEEINTEL: return "FloatingPointModeIEEEINTEL"; - case ExecutionModeMaxWorkgroupSizeINTEL: return "MaxWorkgroupSizeINTEL"; - case ExecutionModeMaxWorkDimINTEL: return "MaxWorkDimINTEL"; - case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL"; - case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL"; - case ExecutionModeSchedulerTargetFmaxMhzINTEL: return "SchedulerTargetFmaxMhzINTEL"; - case ExecutionModeMaximallyReconvergesKHR: return "MaximallyReconvergesKHR"; - case ExecutionModeFPFastMathDefault: return "FPFastMathDefault"; - case ExecutionModeStreamingInterfaceINTEL: return "StreamingInterfaceINTEL"; - case ExecutionModeRegisterMapInterfaceINTEL: return "RegisterMapInterfaceINTEL"; - case ExecutionModeNamedBarrierCountINTEL: return "NamedBarrierCountINTEL"; - case ExecutionModeMaximumRegistersINTEL: return "MaximumRegistersINTEL"; - case ExecutionModeMaximumRegistersIdINTEL: return "MaximumRegistersIdINTEL"; - case ExecutionModeNamedMaximumRegistersINTEL: return "NamedMaximumRegistersINTEL"; - default: return "Unknown"; - } -} - -inline const char* StorageClassToString(StorageClass value) { - switch (value) { - case StorageClassUniformConstant: return "UniformConstant"; - case StorageClassInput: return "Input"; - case StorageClassUniform: return "Uniform"; - case StorageClassOutput: return "Output"; - case StorageClassWorkgroup: return "Workgroup"; - case StorageClassCrossWorkgroup: return "CrossWorkgroup"; - case StorageClassPrivate: return "Private"; - case StorageClassFunction: return "Function"; - case StorageClassGeneric: return "Generic"; - case StorageClassPushConstant: return "PushConstant"; - case StorageClassAtomicCounter: return "AtomicCounter"; - case StorageClassImage: return "Image"; - case StorageClassStorageBuffer: return "StorageBuffer"; - case StorageClassTileImageEXT: return "TileImageEXT"; - case StorageClassNodePayloadAMDX: return "NodePayloadAMDX"; - case StorageClassCallableDataKHR: return "CallableDataKHR"; - case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR"; - case StorageClassRayPayloadKHR: return "RayPayloadKHR"; - case StorageClassHitAttributeKHR: return "HitAttributeKHR"; - case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR"; - case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR"; - case StorageClassPhysicalStorageBuffer: return "PhysicalStorageBuffer"; - case StorageClassHitObjectAttributeNV: return "HitObjectAttributeNV"; - case StorageClassTaskPayloadWorkgroupEXT: return "TaskPayloadWorkgroupEXT"; - case StorageClassCodeSectionINTEL: return "CodeSectionINTEL"; - case StorageClassDeviceOnlyINTEL: return "DeviceOnlyINTEL"; - case StorageClassHostOnlyINTEL: return "HostOnlyINTEL"; - default: return "Unknown"; - } -} - -inline const char* DimToString(Dim value) { - switch (value) { - case Dim1D: return "1D"; - case Dim2D: return "2D"; - case Dim3D: return "3D"; - case DimCube: return "Cube"; - case DimRect: return "Rect"; - case DimBuffer: return "Buffer"; - case DimSubpassData: return "SubpassData"; - case DimTileImageDataEXT: return "TileImageDataEXT"; - default: return "Unknown"; - } -} - -inline const char* SamplerAddressingModeToString(SamplerAddressingMode value) { - switch (value) { - case SamplerAddressingModeNone: return "None"; - case SamplerAddressingModeClampToEdge: return "ClampToEdge"; - case SamplerAddressingModeClamp: return "Clamp"; - case SamplerAddressingModeRepeat: return "Repeat"; - case SamplerAddressingModeRepeatMirrored: return "RepeatMirrored"; - default: return "Unknown"; - } -} - -inline const char* SamplerFilterModeToString(SamplerFilterMode value) { - switch (value) { - case SamplerFilterModeNearest: return "Nearest"; - case SamplerFilterModeLinear: return "Linear"; - default: return "Unknown"; - } -} - -inline const char* ImageFormatToString(ImageFormat value) { - switch (value) { - case ImageFormatUnknown: return "Unknown"; - case ImageFormatRgba32f: return "Rgba32f"; - case ImageFormatRgba16f: return "Rgba16f"; - case ImageFormatR32f: return "R32f"; - case ImageFormatRgba8: return "Rgba8"; - case ImageFormatRgba8Snorm: return "Rgba8Snorm"; - case ImageFormatRg32f: return "Rg32f"; - case ImageFormatRg16f: return "Rg16f"; - case ImageFormatR11fG11fB10f: return "R11fG11fB10f"; - case ImageFormatR16f: return "R16f"; - case ImageFormatRgba16: return "Rgba16"; - case ImageFormatRgb10A2: return "Rgb10A2"; - case ImageFormatRg16: return "Rg16"; - case ImageFormatRg8: return "Rg8"; - case ImageFormatR16: return "R16"; - case ImageFormatR8: return "R8"; - case ImageFormatRgba16Snorm: return "Rgba16Snorm"; - case ImageFormatRg16Snorm: return "Rg16Snorm"; - case ImageFormatRg8Snorm: return "Rg8Snorm"; - case ImageFormatR16Snorm: return "R16Snorm"; - case ImageFormatR8Snorm: return "R8Snorm"; - case ImageFormatRgba32i: return "Rgba32i"; - case ImageFormatRgba16i: return "Rgba16i"; - case ImageFormatRgba8i: return "Rgba8i"; - case ImageFormatR32i: return "R32i"; - case ImageFormatRg32i: return "Rg32i"; - case ImageFormatRg16i: return "Rg16i"; - case ImageFormatRg8i: return "Rg8i"; - case ImageFormatR16i: return "R16i"; - case ImageFormatR8i: return "R8i"; - case ImageFormatRgba32ui: return "Rgba32ui"; - case ImageFormatRgba16ui: return "Rgba16ui"; - case ImageFormatRgba8ui: return "Rgba8ui"; - case ImageFormatR32ui: return "R32ui"; - case ImageFormatRgb10a2ui: return "Rgb10a2ui"; - case ImageFormatRg32ui: return "Rg32ui"; - case ImageFormatRg16ui: return "Rg16ui"; - case ImageFormatRg8ui: return "Rg8ui"; - case ImageFormatR16ui: return "R16ui"; - case ImageFormatR8ui: return "R8ui"; - case ImageFormatR64ui: return "R64ui"; - case ImageFormatR64i: return "R64i"; - default: return "Unknown"; - } -} - -inline const char* ImageChannelOrderToString(ImageChannelOrder value) { - switch (value) { - case ImageChannelOrderR: return "R"; - case ImageChannelOrderA: return "A"; - case ImageChannelOrderRG: return "RG"; - case ImageChannelOrderRA: return "RA"; - case ImageChannelOrderRGB: return "RGB"; - case ImageChannelOrderRGBA: return "RGBA"; - case ImageChannelOrderBGRA: return "BGRA"; - case ImageChannelOrderARGB: return "ARGB"; - case ImageChannelOrderIntensity: return "Intensity"; - case ImageChannelOrderLuminance: return "Luminance"; - case ImageChannelOrderRx: return "Rx"; - case ImageChannelOrderRGx: return "RGx"; - case ImageChannelOrderRGBx: return "RGBx"; - case ImageChannelOrderDepth: return "Depth"; - case ImageChannelOrderDepthStencil: return "DepthStencil"; - case ImageChannelOrdersRGB: return "sRGB"; - case ImageChannelOrdersRGBx: return "sRGBx"; - case ImageChannelOrdersRGBA: return "sRGBA"; - case ImageChannelOrdersBGRA: return "sBGRA"; - case ImageChannelOrderABGR: return "ABGR"; - default: return "Unknown"; - } -} - -inline const char* ImageChannelDataTypeToString(ImageChannelDataType value) { - switch (value) { - case ImageChannelDataTypeSnormInt8: return "SnormInt8"; - case ImageChannelDataTypeSnormInt16: return "SnormInt16"; - case ImageChannelDataTypeUnormInt8: return "UnormInt8"; - case ImageChannelDataTypeUnormInt16: return "UnormInt16"; - case ImageChannelDataTypeUnormShort565: return "UnormShort565"; - case ImageChannelDataTypeUnormShort555: return "UnormShort555"; - case ImageChannelDataTypeUnormInt101010: return "UnormInt101010"; - case ImageChannelDataTypeSignedInt8: return "SignedInt8"; - case ImageChannelDataTypeSignedInt16: return "SignedInt16"; - case ImageChannelDataTypeSignedInt32: return "SignedInt32"; - case ImageChannelDataTypeUnsignedInt8: return "UnsignedInt8"; - case ImageChannelDataTypeUnsignedInt16: return "UnsignedInt16"; - case ImageChannelDataTypeUnsignedInt32: return "UnsignedInt32"; - case ImageChannelDataTypeHalfFloat: return "HalfFloat"; - case ImageChannelDataTypeFloat: return "Float"; - case ImageChannelDataTypeUnormInt24: return "UnormInt24"; - case ImageChannelDataTypeUnormInt101010_2: return "UnormInt101010_2"; - case ImageChannelDataTypeUnsignedIntRaw10EXT: return "UnsignedIntRaw10EXT"; - case ImageChannelDataTypeUnsignedIntRaw12EXT: return "UnsignedIntRaw12EXT"; - case ImageChannelDataTypeUnormInt2_101010EXT: return "UnormInt2_101010EXT"; - default: return "Unknown"; - } -} - -inline const char* FPRoundingModeToString(FPRoundingMode value) { - switch (value) { - case FPRoundingModeRTE: return "RTE"; - case FPRoundingModeRTZ: return "RTZ"; - case FPRoundingModeRTP: return "RTP"; - case FPRoundingModeRTN: return "RTN"; - default: return "Unknown"; - } -} - -inline const char* LinkageTypeToString(LinkageType value) { - switch (value) { - case LinkageTypeExport: return "Export"; - case LinkageTypeImport: return "Import"; - case LinkageTypeLinkOnceODR: return "LinkOnceODR"; - default: return "Unknown"; - } -} - -inline const char* AccessQualifierToString(AccessQualifier value) { - switch (value) { - case AccessQualifierReadOnly: return "ReadOnly"; - case AccessQualifierWriteOnly: return "WriteOnly"; - case AccessQualifierReadWrite: return "ReadWrite"; - default: return "Unknown"; - } -} - -inline const char* FunctionParameterAttributeToString(FunctionParameterAttribute value) { - switch (value) { - case FunctionParameterAttributeZext: return "Zext"; - case FunctionParameterAttributeSext: return "Sext"; - case FunctionParameterAttributeByVal: return "ByVal"; - case FunctionParameterAttributeSret: return "Sret"; - case FunctionParameterAttributeNoAlias: return "NoAlias"; - case FunctionParameterAttributeNoCapture: return "NoCapture"; - case FunctionParameterAttributeNoWrite: return "NoWrite"; - case FunctionParameterAttributeNoReadWrite: return "NoReadWrite"; - case FunctionParameterAttributeRuntimeAlignedINTEL: return "RuntimeAlignedINTEL"; - default: return "Unknown"; - } -} - -inline const char* DecorationToString(Decoration value) { - switch (value) { - case DecorationRelaxedPrecision: return "RelaxedPrecision"; - case DecorationSpecId: return "SpecId"; - case DecorationBlock: return "Block"; - case DecorationBufferBlock: return "BufferBlock"; - case DecorationRowMajor: return "RowMajor"; - case DecorationColMajor: return "ColMajor"; - case DecorationArrayStride: return "ArrayStride"; - case DecorationMatrixStride: return "MatrixStride"; - case DecorationGLSLShared: return "GLSLShared"; - case DecorationGLSLPacked: return "GLSLPacked"; - case DecorationCPacked: return "CPacked"; - case DecorationBuiltIn: return "BuiltIn"; - case DecorationNoPerspective: return "NoPerspective"; - case DecorationFlat: return "Flat"; - case DecorationPatch: return "Patch"; - case DecorationCentroid: return "Centroid"; - case DecorationSample: return "Sample"; - case DecorationInvariant: return "Invariant"; - case DecorationRestrict: return "Restrict"; - case DecorationAliased: return "Aliased"; - case DecorationVolatile: return "Volatile"; - case DecorationConstant: return "Constant"; - case DecorationCoherent: return "Coherent"; - case DecorationNonWritable: return "NonWritable"; - case DecorationNonReadable: return "NonReadable"; - case DecorationUniform: return "Uniform"; - case DecorationUniformId: return "UniformId"; - case DecorationSaturatedConversion: return "SaturatedConversion"; - case DecorationStream: return "Stream"; - case DecorationLocation: return "Location"; - case DecorationComponent: return "Component"; - case DecorationIndex: return "Index"; - case DecorationBinding: return "Binding"; - case DecorationDescriptorSet: return "DescriptorSet"; - case DecorationOffset: return "Offset"; - case DecorationXfbBuffer: return "XfbBuffer"; - case DecorationXfbStride: return "XfbStride"; - case DecorationFuncParamAttr: return "FuncParamAttr"; - case DecorationFPRoundingMode: return "FPRoundingMode"; - case DecorationFPFastMathMode: return "FPFastMathMode"; - case DecorationLinkageAttributes: return "LinkageAttributes"; - case DecorationNoContraction: return "NoContraction"; - case DecorationInputAttachmentIndex: return "InputAttachmentIndex"; - case DecorationAlignment: return "Alignment"; - case DecorationMaxByteOffset: return "MaxByteOffset"; - case DecorationAlignmentId: return "AlignmentId"; - case DecorationMaxByteOffsetId: return "MaxByteOffsetId"; - case DecorationNoSignedWrap: return "NoSignedWrap"; - case DecorationNoUnsignedWrap: return "NoUnsignedWrap"; - case DecorationWeightTextureQCOM: return "WeightTextureQCOM"; - case DecorationBlockMatchTextureQCOM: return "BlockMatchTextureQCOM"; - case DecorationBlockMatchSamplerQCOM: return "BlockMatchSamplerQCOM"; - case DecorationExplicitInterpAMD: return "ExplicitInterpAMD"; - case DecorationNodeSharesPayloadLimitsWithAMDX: return "NodeSharesPayloadLimitsWithAMDX"; - case DecorationNodeMaxPayloadsAMDX: return "NodeMaxPayloadsAMDX"; - case DecorationTrackFinishWritingAMDX: return "TrackFinishWritingAMDX"; - case DecorationPayloadNodeNameAMDX: return "PayloadNodeNameAMDX"; - case DecorationPayloadNodeBaseIndexAMDX: return "PayloadNodeBaseIndexAMDX"; - case DecorationPayloadNodeSparseArrayAMDX: return "PayloadNodeSparseArrayAMDX"; - case DecorationPayloadNodeArraySizeAMDX: return "PayloadNodeArraySizeAMDX"; - case DecorationPayloadDispatchIndirectAMDX: return "PayloadDispatchIndirectAMDX"; - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; - case DecorationPerPrimitiveEXT: return "PerPrimitiveEXT"; - case DecorationPerViewNV: return "PerViewNV"; - case DecorationPerTaskNV: return "PerTaskNV"; - case DecorationPerVertexKHR: return "PerVertexKHR"; - case DecorationNonUniform: return "NonUniform"; - case DecorationRestrictPointer: return "RestrictPointer"; - case DecorationAliasedPointer: return "AliasedPointer"; - case DecorationHitObjectShaderRecordBufferNV: return "HitObjectShaderRecordBufferNV"; - case DecorationBindlessSamplerNV: return "BindlessSamplerNV"; - case DecorationBindlessImageNV: return "BindlessImageNV"; - case DecorationBoundSamplerNV: return "BoundSamplerNV"; - case DecorationBoundImageNV: return "BoundImageNV"; - case DecorationSIMTCallINTEL: return "SIMTCallINTEL"; - case DecorationReferencedIndirectlyINTEL: return "ReferencedIndirectlyINTEL"; - case DecorationClobberINTEL: return "ClobberINTEL"; - case DecorationSideEffectsINTEL: return "SideEffectsINTEL"; - case DecorationVectorComputeVariableINTEL: return "VectorComputeVariableINTEL"; - case DecorationFuncParamIOKindINTEL: return "FuncParamIOKindINTEL"; - case DecorationVectorComputeFunctionINTEL: return "VectorComputeFunctionINTEL"; - case DecorationStackCallINTEL: return "StackCallINTEL"; - case DecorationGlobalVariableOffsetINTEL: return "GlobalVariableOffsetINTEL"; - case DecorationCounterBuffer: return "CounterBuffer"; - case DecorationHlslSemanticGOOGLE: return "HlslSemanticGOOGLE"; - case DecorationUserTypeGOOGLE: return "UserTypeGOOGLE"; - case DecorationFunctionRoundingModeINTEL: return "FunctionRoundingModeINTEL"; - case DecorationFunctionDenormModeINTEL: return "FunctionDenormModeINTEL"; - case DecorationRegisterINTEL: return "RegisterINTEL"; - case DecorationMemoryINTEL: return "MemoryINTEL"; - case DecorationNumbanksINTEL: return "NumbanksINTEL"; - case DecorationBankwidthINTEL: return "BankwidthINTEL"; - case DecorationMaxPrivateCopiesINTEL: return "MaxPrivateCopiesINTEL"; - case DecorationSinglepumpINTEL: return "SinglepumpINTEL"; - case DecorationDoublepumpINTEL: return "DoublepumpINTEL"; - case DecorationMaxReplicatesINTEL: return "MaxReplicatesINTEL"; - case DecorationSimpleDualPortINTEL: return "SimpleDualPortINTEL"; - case DecorationMergeINTEL: return "MergeINTEL"; - case DecorationBankBitsINTEL: return "BankBitsINTEL"; - case DecorationForcePow2DepthINTEL: return "ForcePow2DepthINTEL"; - case DecorationStridesizeINTEL: return "StridesizeINTEL"; - case DecorationWordsizeINTEL: return "WordsizeINTEL"; - case DecorationTrueDualPortINTEL: return "TrueDualPortINTEL"; - case DecorationBurstCoalesceINTEL: return "BurstCoalesceINTEL"; - case DecorationCacheSizeINTEL: return "CacheSizeINTEL"; - case DecorationDontStaticallyCoalesceINTEL: return "DontStaticallyCoalesceINTEL"; - case DecorationPrefetchINTEL: return "PrefetchINTEL"; - case DecorationStallEnableINTEL: return "StallEnableINTEL"; - case DecorationFuseLoopsInFunctionINTEL: return "FuseLoopsInFunctionINTEL"; - case DecorationMathOpDSPModeINTEL: return "MathOpDSPModeINTEL"; - case DecorationAliasScopeINTEL: return "AliasScopeINTEL"; - case DecorationNoAliasINTEL: return "NoAliasINTEL"; - case DecorationInitiationIntervalINTEL: return "InitiationIntervalINTEL"; - case DecorationMaxConcurrencyINTEL: return "MaxConcurrencyINTEL"; - case DecorationPipelineEnableINTEL: return "PipelineEnableINTEL"; - case DecorationBufferLocationINTEL: return "BufferLocationINTEL"; - case DecorationIOPipeStorageINTEL: return "IOPipeStorageINTEL"; - case DecorationFunctionFloatingPointModeINTEL: return "FunctionFloatingPointModeINTEL"; - case DecorationSingleElementVectorINTEL: return "SingleElementVectorINTEL"; - case DecorationVectorComputeCallableFunctionINTEL: return "VectorComputeCallableFunctionINTEL"; - case DecorationMediaBlockIOINTEL: return "MediaBlockIOINTEL"; - case DecorationStallFreeINTEL: return "StallFreeINTEL"; - case DecorationFPMaxErrorDecorationINTEL: return "FPMaxErrorDecorationINTEL"; - case DecorationLatencyControlLabelINTEL: return "LatencyControlLabelINTEL"; - case DecorationLatencyControlConstraintINTEL: return "LatencyControlConstraintINTEL"; - case DecorationConduitKernelArgumentINTEL: return "ConduitKernelArgumentINTEL"; - case DecorationRegisterMapKernelArgumentINTEL: return "RegisterMapKernelArgumentINTEL"; - case DecorationMMHostInterfaceAddressWidthINTEL: return "MMHostInterfaceAddressWidthINTEL"; - case DecorationMMHostInterfaceDataWidthINTEL: return "MMHostInterfaceDataWidthINTEL"; - case DecorationMMHostInterfaceLatencyINTEL: return "MMHostInterfaceLatencyINTEL"; - case DecorationMMHostInterfaceReadWriteModeINTEL: return "MMHostInterfaceReadWriteModeINTEL"; - case DecorationMMHostInterfaceMaxBurstINTEL: return "MMHostInterfaceMaxBurstINTEL"; - case DecorationMMHostInterfaceWaitRequestINTEL: return "MMHostInterfaceWaitRequestINTEL"; - case DecorationStableKernelArgumentINTEL: return "StableKernelArgumentINTEL"; - case DecorationHostAccessINTEL: return "HostAccessINTEL"; - case DecorationInitModeINTEL: return "InitModeINTEL"; - case DecorationImplementInRegisterMapINTEL: return "ImplementInRegisterMapINTEL"; - case DecorationCacheControlLoadINTEL: return "CacheControlLoadINTEL"; - case DecorationCacheControlStoreINTEL: return "CacheControlStoreINTEL"; - default: return "Unknown"; - } -} - -inline const char* BuiltInToString(BuiltIn value) { - switch (value) { - case BuiltInPosition: return "Position"; - case BuiltInPointSize: return "PointSize"; - case BuiltInClipDistance: return "ClipDistance"; - case BuiltInCullDistance: return "CullDistance"; - case BuiltInVertexId: return "VertexId"; - case BuiltInInstanceId: return "InstanceId"; - case BuiltInPrimitiveId: return "PrimitiveId"; - case BuiltInInvocationId: return "InvocationId"; - case BuiltInLayer: return "Layer"; - case BuiltInViewportIndex: return "ViewportIndex"; - case BuiltInTessLevelOuter: return "TessLevelOuter"; - case BuiltInTessLevelInner: return "TessLevelInner"; - case BuiltInTessCoord: return "TessCoord"; - case BuiltInPatchVertices: return "PatchVertices"; - case BuiltInFragCoord: return "FragCoord"; - case BuiltInPointCoord: return "PointCoord"; - case BuiltInFrontFacing: return "FrontFacing"; - case BuiltInSampleId: return "SampleId"; - case BuiltInSamplePosition: return "SamplePosition"; - case BuiltInSampleMask: return "SampleMask"; - case BuiltInFragDepth: return "FragDepth"; - case BuiltInHelperInvocation: return "HelperInvocation"; - case BuiltInNumWorkgroups: return "NumWorkgroups"; - case BuiltInWorkgroupSize: return "WorkgroupSize"; - case BuiltInWorkgroupId: return "WorkgroupId"; - case BuiltInLocalInvocationId: return "LocalInvocationId"; - case BuiltInGlobalInvocationId: return "GlobalInvocationId"; - case BuiltInLocalInvocationIndex: return "LocalInvocationIndex"; - case BuiltInWorkDim: return "WorkDim"; - case BuiltInGlobalSize: return "GlobalSize"; - case BuiltInEnqueuedWorkgroupSize: return "EnqueuedWorkgroupSize"; - case BuiltInGlobalOffset: return "GlobalOffset"; - case BuiltInGlobalLinearId: return "GlobalLinearId"; - case BuiltInSubgroupSize: return "SubgroupSize"; - case BuiltInSubgroupMaxSize: return "SubgroupMaxSize"; - case BuiltInNumSubgroups: return "NumSubgroups"; - case BuiltInNumEnqueuedSubgroups: return "NumEnqueuedSubgroups"; - case BuiltInSubgroupId: return "SubgroupId"; - case BuiltInSubgroupLocalInvocationId: return "SubgroupLocalInvocationId"; - case BuiltInVertexIndex: return "VertexIndex"; - case BuiltInInstanceIndex: return "InstanceIndex"; - case BuiltInCoreIDARM: return "CoreIDARM"; - case BuiltInCoreCountARM: return "CoreCountARM"; - case BuiltInCoreMaxIDARM: return "CoreMaxIDARM"; - case BuiltInWarpIDARM: return "WarpIDARM"; - case BuiltInWarpMaxIDARM: return "WarpMaxIDARM"; - case BuiltInSubgroupEqMask: return "SubgroupEqMask"; - case BuiltInSubgroupGeMask: return "SubgroupGeMask"; - case BuiltInSubgroupGtMask: return "SubgroupGtMask"; - case BuiltInSubgroupLeMask: return "SubgroupLeMask"; - case BuiltInSubgroupLtMask: return "SubgroupLtMask"; - case BuiltInBaseVertex: return "BaseVertex"; - case BuiltInBaseInstance: return "BaseInstance"; - case BuiltInDrawIndex: return "DrawIndex"; - case BuiltInPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR"; - case BuiltInDeviceIndex: return "DeviceIndex"; - case BuiltInViewIndex: return "ViewIndex"; - case BuiltInShadingRateKHR: return "ShadingRateKHR"; - case BuiltInBaryCoordNoPerspAMD: return "BaryCoordNoPerspAMD"; - case BuiltInBaryCoordNoPerspCentroidAMD: return "BaryCoordNoPerspCentroidAMD"; - case BuiltInBaryCoordNoPerspSampleAMD: return "BaryCoordNoPerspSampleAMD"; - case BuiltInBaryCoordSmoothAMD: return "BaryCoordSmoothAMD"; - case BuiltInBaryCoordSmoothCentroidAMD: return "BaryCoordSmoothCentroidAMD"; - case BuiltInBaryCoordSmoothSampleAMD: return "BaryCoordSmoothSampleAMD"; - case BuiltInBaryCoordPullModelAMD: return "BaryCoordPullModelAMD"; - case BuiltInFragStencilRefEXT: return "FragStencilRefEXT"; - case BuiltInRemainingRecursionLevelsAMDX: return "RemainingRecursionLevelsAMDX"; - case BuiltInShaderIndexAMDX: return "ShaderIndexAMDX"; - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case BuiltInFullyCoveredEXT: return "FullyCoveredEXT"; - case BuiltInTaskCountNV: return "TaskCountNV"; - case BuiltInPrimitiveCountNV: return "PrimitiveCountNV"; - case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV"; - case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV"; - case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV"; - case BuiltInLayerPerViewNV: return "LayerPerViewNV"; - case BuiltInMeshViewCountNV: return "MeshViewCountNV"; - case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV"; - case BuiltInBaryCoordKHR: return "BaryCoordKHR"; - case BuiltInBaryCoordNoPerspKHR: return "BaryCoordNoPerspKHR"; - case BuiltInFragSizeEXT: return "FragSizeEXT"; - case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; - case BuiltInPrimitivePointIndicesEXT: return "PrimitivePointIndicesEXT"; - case BuiltInPrimitiveLineIndicesEXT: return "PrimitiveLineIndicesEXT"; - case BuiltInPrimitiveTriangleIndicesEXT: return "PrimitiveTriangleIndicesEXT"; - case BuiltInCullPrimitiveEXT: return "CullPrimitiveEXT"; - case BuiltInLaunchIdKHR: return "LaunchIdKHR"; - case BuiltInLaunchSizeKHR: return "LaunchSizeKHR"; - case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR"; - case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR"; - case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR"; - case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR"; - case BuiltInRayTminKHR: return "RayTminKHR"; - case BuiltInRayTmaxKHR: return "RayTmaxKHR"; - case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR"; - case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR"; - case BuiltInWorldToObjectKHR: return "WorldToObjectKHR"; - case BuiltInHitTNV: return "HitTNV"; - case BuiltInHitKindKHR: return "HitKindKHR"; - case BuiltInCurrentRayTimeNV: return "CurrentRayTimeNV"; - case BuiltInHitTriangleVertexPositionsKHR: return "HitTriangleVertexPositionsKHR"; - case BuiltInHitMicroTriangleVertexPositionsNV: return "HitMicroTriangleVertexPositionsNV"; - case BuiltInHitMicroTriangleVertexBarycentricsNV: return "HitMicroTriangleVertexBarycentricsNV"; - case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR"; - case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR"; - case BuiltInWarpsPerSMNV: return "WarpsPerSMNV"; - case BuiltInSMCountNV: return "SMCountNV"; - case BuiltInWarpIDNV: return "WarpIDNV"; - case BuiltInSMIDNV: return "SMIDNV"; - case BuiltInHitKindFrontFacingMicroTriangleNV: return "HitKindFrontFacingMicroTriangleNV"; - case BuiltInHitKindBackFacingMicroTriangleNV: return "HitKindBackFacingMicroTriangleNV"; - case BuiltInCullMaskKHR: return "CullMaskKHR"; - default: return "Unknown"; - } -} - -inline const char* ScopeToString(Scope value) { - switch (value) { - case ScopeCrossDevice: return "CrossDevice"; - case ScopeDevice: return "Device"; - case ScopeWorkgroup: return "Workgroup"; - case ScopeSubgroup: return "Subgroup"; - case ScopeInvocation: return "Invocation"; - case ScopeQueueFamily: return "QueueFamily"; - case ScopeShaderCallKHR: return "ShaderCallKHR"; - default: return "Unknown"; - } -} - -inline const char* GroupOperationToString(GroupOperation value) { - switch (value) { - case GroupOperationReduce: return "Reduce"; - case GroupOperationInclusiveScan: return "InclusiveScan"; - case GroupOperationExclusiveScan: return "ExclusiveScan"; - case GroupOperationClusteredReduce: return "ClusteredReduce"; - case GroupOperationPartitionedReduceNV: return "PartitionedReduceNV"; - case GroupOperationPartitionedInclusiveScanNV: return "PartitionedInclusiveScanNV"; - case GroupOperationPartitionedExclusiveScanNV: return "PartitionedExclusiveScanNV"; - default: return "Unknown"; - } -} - -inline const char* KernelEnqueueFlagsToString(KernelEnqueueFlags value) { - switch (value) { - case KernelEnqueueFlagsNoWait: return "NoWait"; - case KernelEnqueueFlagsWaitKernel: return "WaitKernel"; - case KernelEnqueueFlagsWaitWorkGroup: return "WaitWorkGroup"; - default: return "Unknown"; - } -} - -inline const char* CapabilityToString(Capability value) { - switch (value) { - case CapabilityMatrix: return "Matrix"; - case CapabilityShader: return "Shader"; - case CapabilityGeometry: return "Geometry"; - case CapabilityTessellation: return "Tessellation"; - case CapabilityAddresses: return "Addresses"; - case CapabilityLinkage: return "Linkage"; - case CapabilityKernel: return "Kernel"; - case CapabilityVector16: return "Vector16"; - case CapabilityFloat16Buffer: return "Float16Buffer"; - case CapabilityFloat16: return "Float16"; - case CapabilityFloat64: return "Float64"; - case CapabilityInt64: return "Int64"; - case CapabilityInt64Atomics: return "Int64Atomics"; - case CapabilityImageBasic: return "ImageBasic"; - case CapabilityImageReadWrite: return "ImageReadWrite"; - case CapabilityImageMipmap: return "ImageMipmap"; - case CapabilityPipes: return "Pipes"; - case CapabilityGroups: return "Groups"; - case CapabilityDeviceEnqueue: return "DeviceEnqueue"; - case CapabilityLiteralSampler: return "LiteralSampler"; - case CapabilityAtomicStorage: return "AtomicStorage"; - case CapabilityInt16: return "Int16"; - case CapabilityTessellationPointSize: return "TessellationPointSize"; - case CapabilityGeometryPointSize: return "GeometryPointSize"; - case CapabilityImageGatherExtended: return "ImageGatherExtended"; - case CapabilityStorageImageMultisample: return "StorageImageMultisample"; - case CapabilityUniformBufferArrayDynamicIndexing: return "UniformBufferArrayDynamicIndexing"; - case CapabilitySampledImageArrayDynamicIndexing: return "SampledImageArrayDynamicIndexing"; - case CapabilityStorageBufferArrayDynamicIndexing: return "StorageBufferArrayDynamicIndexing"; - case CapabilityStorageImageArrayDynamicIndexing: return "StorageImageArrayDynamicIndexing"; - case CapabilityClipDistance: return "ClipDistance"; - case CapabilityCullDistance: return "CullDistance"; - case CapabilityImageCubeArray: return "ImageCubeArray"; - case CapabilitySampleRateShading: return "SampleRateShading"; - case CapabilityImageRect: return "ImageRect"; - case CapabilitySampledRect: return "SampledRect"; - case CapabilityGenericPointer: return "GenericPointer"; - case CapabilityInt8: return "Int8"; - case CapabilityInputAttachment: return "InputAttachment"; - case CapabilitySparseResidency: return "SparseResidency"; - case CapabilityMinLod: return "MinLod"; - case CapabilitySampled1D: return "Sampled1D"; - case CapabilityImage1D: return "Image1D"; - case CapabilitySampledCubeArray: return "SampledCubeArray"; - case CapabilitySampledBuffer: return "SampledBuffer"; - case CapabilityImageBuffer: return "ImageBuffer"; - case CapabilityImageMSArray: return "ImageMSArray"; - case CapabilityStorageImageExtendedFormats: return "StorageImageExtendedFormats"; - case CapabilityImageQuery: return "ImageQuery"; - case CapabilityDerivativeControl: return "DerivativeControl"; - case CapabilityInterpolationFunction: return "InterpolationFunction"; - case CapabilityTransformFeedback: return "TransformFeedback"; - case CapabilityGeometryStreams: return "GeometryStreams"; - case CapabilityStorageImageReadWithoutFormat: return "StorageImageReadWithoutFormat"; - case CapabilityStorageImageWriteWithoutFormat: return "StorageImageWriteWithoutFormat"; - case CapabilityMultiViewport: return "MultiViewport"; - case CapabilitySubgroupDispatch: return "SubgroupDispatch"; - case CapabilityNamedBarrier: return "NamedBarrier"; - case CapabilityPipeStorage: return "PipeStorage"; - case CapabilityGroupNonUniform: return "GroupNonUniform"; - case CapabilityGroupNonUniformVote: return "GroupNonUniformVote"; - case CapabilityGroupNonUniformArithmetic: return "GroupNonUniformArithmetic"; - case CapabilityGroupNonUniformBallot: return "GroupNonUniformBallot"; - case CapabilityGroupNonUniformShuffle: return "GroupNonUniformShuffle"; - case CapabilityGroupNonUniformShuffleRelative: return "GroupNonUniformShuffleRelative"; - case CapabilityGroupNonUniformClustered: return "GroupNonUniformClustered"; - case CapabilityGroupNonUniformQuad: return "GroupNonUniformQuad"; - case CapabilityShaderLayer: return "ShaderLayer"; - case CapabilityShaderViewportIndex: return "ShaderViewportIndex"; - case CapabilityUniformDecoration: return "UniformDecoration"; - case CapabilityCoreBuiltinsARM: return "CoreBuiltinsARM"; - case CapabilityTileImageColorReadAccessEXT: return "TileImageColorReadAccessEXT"; - case CapabilityTileImageDepthReadAccessEXT: return "TileImageDepthReadAccessEXT"; - case CapabilityTileImageStencilReadAccessEXT: return "TileImageStencilReadAccessEXT"; - case CapabilityCooperativeMatrixLayoutsARM: return "CooperativeMatrixLayoutsARM"; - case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR"; - case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR"; - case CapabilityDrawParameters: return "DrawParameters"; - case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "WorkgroupMemoryExplicitLayoutKHR"; - case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "WorkgroupMemoryExplicitLayout8BitAccessKHR"; - case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "WorkgroupMemoryExplicitLayout16BitAccessKHR"; - case CapabilitySubgroupVoteKHR: return "SubgroupVoteKHR"; - case CapabilityStorageBuffer16BitAccess: return "StorageBuffer16BitAccess"; - case CapabilityStorageUniform16: return "StorageUniform16"; - case CapabilityStoragePushConstant16: return "StoragePushConstant16"; - case CapabilityStorageInputOutput16: return "StorageInputOutput16"; - case CapabilityDeviceGroup: return "DeviceGroup"; - case CapabilityMultiView: return "MultiView"; - case CapabilityVariablePointersStorageBuffer: return "VariablePointersStorageBuffer"; - case CapabilityVariablePointers: return "VariablePointers"; - case CapabilityAtomicStorageOps: return "AtomicStorageOps"; - case CapabilitySampleMaskPostDepthCoverage: return "SampleMaskPostDepthCoverage"; - case CapabilityStorageBuffer8BitAccess: return "StorageBuffer8BitAccess"; - case CapabilityUniformAndStorageBuffer8BitAccess: return "UniformAndStorageBuffer8BitAccess"; - case CapabilityStoragePushConstant8: return "StoragePushConstant8"; - case CapabilityDenormPreserve: return "DenormPreserve"; - case CapabilityDenormFlushToZero: return "DenormFlushToZero"; - case CapabilitySignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; - case CapabilityRoundingModeRTE: return "RoundingModeRTE"; - case CapabilityRoundingModeRTZ: return "RoundingModeRTZ"; - case CapabilityRayQueryProvisionalKHR: return "RayQueryProvisionalKHR"; - case CapabilityRayQueryKHR: return "RayQueryKHR"; - case CapabilityUntypedPointersKHR: return "UntypedPointersKHR"; - case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR"; - case CapabilityRayTracingKHR: return "RayTracingKHR"; - case CapabilityTextureSampleWeightedQCOM: return "TextureSampleWeightedQCOM"; - case CapabilityTextureBoxFilterQCOM: return "TextureBoxFilterQCOM"; - case CapabilityTextureBlockMatchQCOM: return "TextureBlockMatchQCOM"; - case CapabilityTextureBlockMatch2QCOM: return "TextureBlockMatch2QCOM"; - case CapabilityFloat16ImageAMD: return "Float16ImageAMD"; - case CapabilityImageGatherBiasLodAMD: return "ImageGatherBiasLodAMD"; - case CapabilityFragmentMaskAMD: return "FragmentMaskAMD"; - case CapabilityStencilExportEXT: return "StencilExportEXT"; - case CapabilityImageReadWriteLodAMD: return "ImageReadWriteLodAMD"; - case CapabilityInt64ImageEXT: return "Int64ImageEXT"; - case CapabilityShaderClockKHR: return "ShaderClockKHR"; - case CapabilityShaderEnqueueAMDX: return "ShaderEnqueueAMDX"; - case CapabilityQuadControlKHR: return "QuadControlKHR"; - case CapabilitySampleMaskOverrideCoverageNV: return "SampleMaskOverrideCoverageNV"; - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case CapabilityShaderViewportIndexLayerEXT: return "ShaderViewportIndexLayerEXT"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT"; - case CapabilityMeshShadingNV: return "MeshShadingNV"; - case CapabilityImageFootprintNV: return "ImageFootprintNV"; - case CapabilityMeshShadingEXT: return "MeshShadingEXT"; - case CapabilityFragmentBarycentricKHR: return "FragmentBarycentricKHR"; - case CapabilityComputeDerivativeGroupQuadsKHR: return "ComputeDerivativeGroupQuadsKHR"; - case CapabilityFragmentDensityEXT: return "FragmentDensityEXT"; - case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; - case CapabilityShaderNonUniform: return "ShaderNonUniform"; - case CapabilityRuntimeDescriptorArray: return "RuntimeDescriptorArray"; - case CapabilityInputAttachmentArrayDynamicIndexing: return "InputAttachmentArrayDynamicIndexing"; - case CapabilityUniformTexelBufferArrayDynamicIndexing: return "UniformTexelBufferArrayDynamicIndexing"; - case CapabilityStorageTexelBufferArrayDynamicIndexing: return "StorageTexelBufferArrayDynamicIndexing"; - case CapabilityUniformBufferArrayNonUniformIndexing: return "UniformBufferArrayNonUniformIndexing"; - case CapabilitySampledImageArrayNonUniformIndexing: return "SampledImageArrayNonUniformIndexing"; - case CapabilityStorageBufferArrayNonUniformIndexing: return "StorageBufferArrayNonUniformIndexing"; - case CapabilityStorageImageArrayNonUniformIndexing: return "StorageImageArrayNonUniformIndexing"; - case CapabilityInputAttachmentArrayNonUniformIndexing: return "InputAttachmentArrayNonUniformIndexing"; - case CapabilityUniformTexelBufferArrayNonUniformIndexing: return "UniformTexelBufferArrayNonUniformIndexing"; - case CapabilityStorageTexelBufferArrayNonUniformIndexing: return "StorageTexelBufferArrayNonUniformIndexing"; - case CapabilityRayTracingPositionFetchKHR: return "RayTracingPositionFetchKHR"; - case CapabilityRayTracingNV: return "RayTracingNV"; - case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV"; - case CapabilityVulkanMemoryModel: return "VulkanMemoryModel"; - case CapabilityVulkanMemoryModelDeviceScope: return "VulkanMemoryModelDeviceScope"; - case CapabilityPhysicalStorageBufferAddresses: return "PhysicalStorageBufferAddresses"; - case CapabilityComputeDerivativeGroupLinearKHR: return "ComputeDerivativeGroupLinearKHR"; - case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR"; - case CapabilityCooperativeMatrixNV: return "CooperativeMatrixNV"; - case CapabilityFragmentShaderSampleInterlockEXT: return "FragmentShaderSampleInterlockEXT"; - case CapabilityFragmentShaderShadingRateInterlockEXT: return "FragmentShaderShadingRateInterlockEXT"; - case CapabilityShaderSMBuiltinsNV: return "ShaderSMBuiltinsNV"; - case CapabilityFragmentShaderPixelInterlockEXT: return "FragmentShaderPixelInterlockEXT"; - case CapabilityDemoteToHelperInvocation: return "DemoteToHelperInvocation"; - case CapabilityDisplacementMicromapNV: return "DisplacementMicromapNV"; - case CapabilityRayTracingOpacityMicromapEXT: return "RayTracingOpacityMicromapEXT"; - case CapabilityShaderInvocationReorderNV: return "ShaderInvocationReorderNV"; - case CapabilityBindlessTextureNV: return "BindlessTextureNV"; - case CapabilityRayQueryPositionFetchKHR: return "RayQueryPositionFetchKHR"; - case CapabilityAtomicFloat16VectorNV: return "AtomicFloat16VectorNV"; - case CapabilityRayTracingDisplacementMicromapNV: return "RayTracingDisplacementMicromapNV"; - case CapabilityRawAccessChainsNV: return "RawAccessChainsNV"; - case CapabilityCooperativeMatrixReductionsNV: return "CooperativeMatrixReductionsNV"; - case CapabilityCooperativeMatrixConversionsNV: return "CooperativeMatrixConversionsNV"; - case CapabilityCooperativeMatrixPerElementOperationsNV: return "CooperativeMatrixPerElementOperationsNV"; - case CapabilityCooperativeMatrixTensorAddressingNV: return "CooperativeMatrixTensorAddressingNV"; - case CapabilityCooperativeMatrixBlockLoadsNV: return "CooperativeMatrixBlockLoadsNV"; - case CapabilityTensorAddressingNV: return "TensorAddressingNV"; - case CapabilitySubgroupShuffleINTEL: return "SubgroupShuffleINTEL"; - case CapabilitySubgroupBufferBlockIOINTEL: return "SubgroupBufferBlockIOINTEL"; - case CapabilitySubgroupImageBlockIOINTEL: return "SubgroupImageBlockIOINTEL"; - case CapabilitySubgroupImageMediaBlockIOINTEL: return "SubgroupImageMediaBlockIOINTEL"; - case CapabilityRoundToInfinityINTEL: return "RoundToInfinityINTEL"; - case CapabilityFloatingPointModeINTEL: return "FloatingPointModeINTEL"; - case CapabilityIntegerFunctions2INTEL: return "IntegerFunctions2INTEL"; - case CapabilityFunctionPointersINTEL: return "FunctionPointersINTEL"; - case CapabilityIndirectReferencesINTEL: return "IndirectReferencesINTEL"; - case CapabilityAsmINTEL: return "AsmINTEL"; - case CapabilityAtomicFloat32MinMaxEXT: return "AtomicFloat32MinMaxEXT"; - case CapabilityAtomicFloat64MinMaxEXT: return "AtomicFloat64MinMaxEXT"; - case CapabilityAtomicFloat16MinMaxEXT: return "AtomicFloat16MinMaxEXT"; - case CapabilityVectorComputeINTEL: return "VectorComputeINTEL"; - case CapabilityVectorAnyINTEL: return "VectorAnyINTEL"; - case CapabilityExpectAssumeKHR: return "ExpectAssumeKHR"; - case CapabilitySubgroupAvcMotionEstimationINTEL: return "SubgroupAvcMotionEstimationINTEL"; - case CapabilitySubgroupAvcMotionEstimationIntraINTEL: return "SubgroupAvcMotionEstimationIntraINTEL"; - case CapabilitySubgroupAvcMotionEstimationChromaINTEL: return "SubgroupAvcMotionEstimationChromaINTEL"; - case CapabilityVariableLengthArrayINTEL: return "VariableLengthArrayINTEL"; - case CapabilityFunctionFloatControlINTEL: return "FunctionFloatControlINTEL"; - case CapabilityFPGAMemoryAttributesINTEL: return "FPGAMemoryAttributesINTEL"; - case CapabilityFPFastMathModeINTEL: return "FPFastMathModeINTEL"; - case CapabilityArbitraryPrecisionIntegersINTEL: return "ArbitraryPrecisionIntegersINTEL"; - case CapabilityArbitraryPrecisionFloatingPointINTEL: return "ArbitraryPrecisionFloatingPointINTEL"; - case CapabilityUnstructuredLoopControlsINTEL: return "UnstructuredLoopControlsINTEL"; - case CapabilityFPGALoopControlsINTEL: return "FPGALoopControlsINTEL"; - case CapabilityKernelAttributesINTEL: return "KernelAttributesINTEL"; - case CapabilityFPGAKernelAttributesINTEL: return "FPGAKernelAttributesINTEL"; - case CapabilityFPGAMemoryAccessesINTEL: return "FPGAMemoryAccessesINTEL"; - case CapabilityFPGAClusterAttributesINTEL: return "FPGAClusterAttributesINTEL"; - case CapabilityLoopFuseINTEL: return "LoopFuseINTEL"; - case CapabilityFPGADSPControlINTEL: return "FPGADSPControlINTEL"; - case CapabilityMemoryAccessAliasingINTEL: return "MemoryAccessAliasingINTEL"; - case CapabilityFPGAInvocationPipeliningAttributesINTEL: return "FPGAInvocationPipeliningAttributesINTEL"; - case CapabilityFPGABufferLocationINTEL: return "FPGABufferLocationINTEL"; - case CapabilityArbitraryPrecisionFixedPointINTEL: return "ArbitraryPrecisionFixedPointINTEL"; - case CapabilityUSMStorageClassesINTEL: return "USMStorageClassesINTEL"; - case CapabilityRuntimeAlignedAttributeINTEL: return "RuntimeAlignedAttributeINTEL"; - case CapabilityIOPipesINTEL: return "IOPipesINTEL"; - case CapabilityBlockingPipesINTEL: return "BlockingPipesINTEL"; - case CapabilityFPGARegINTEL: return "FPGARegINTEL"; - case CapabilityDotProductInputAll: return "DotProductInputAll"; - case CapabilityDotProductInput4x8Bit: return "DotProductInput4x8Bit"; - case CapabilityDotProductInput4x8BitPacked: return "DotProductInput4x8BitPacked"; - case CapabilityDotProduct: return "DotProduct"; - case CapabilityRayCullMaskKHR: return "RayCullMaskKHR"; - case CapabilityCooperativeMatrixKHR: return "CooperativeMatrixKHR"; - case CapabilityReplicatedCompositesEXT: return "ReplicatedCompositesEXT"; - case CapabilityBitInstructions: return "BitInstructions"; - case CapabilityGroupNonUniformRotateKHR: return "GroupNonUniformRotateKHR"; - case CapabilityFloatControls2: return "FloatControls2"; - case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT"; - case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT"; - case CapabilityLongCompositesINTEL: return "LongCompositesINTEL"; - case CapabilityOptNoneEXT: return "OptNoneEXT"; - case CapabilityAtomicFloat16AddEXT: return "AtomicFloat16AddEXT"; - case CapabilityDebugInfoModuleINTEL: return "DebugInfoModuleINTEL"; - case CapabilityBFloat16ConversionINTEL: return "BFloat16ConversionINTEL"; - case CapabilitySplitBarrierINTEL: return "SplitBarrierINTEL"; - case CapabilityArithmeticFenceEXT: return "ArithmeticFenceEXT"; - case CapabilityFPGAClusterAttributesV2INTEL: return "FPGAClusterAttributesV2INTEL"; - case CapabilityFPGAKernelAttributesv2INTEL: return "FPGAKernelAttributesv2INTEL"; - case CapabilityFPMaxErrorINTEL: return "FPMaxErrorINTEL"; - case CapabilityFPGALatencyControlINTEL: return "FPGALatencyControlINTEL"; - case CapabilityFPGAArgumentInterfacesINTEL: return "FPGAArgumentInterfacesINTEL"; - case CapabilityGlobalVariableHostAccessINTEL: return "GlobalVariableHostAccessINTEL"; - case CapabilityGlobalVariableFPGADecorationsINTEL: return "GlobalVariableFPGADecorationsINTEL"; - case CapabilitySubgroupBufferPrefetchINTEL: return "SubgroupBufferPrefetchINTEL"; - case CapabilityGroupUniformArithmeticKHR: return "GroupUniformArithmeticKHR"; - case CapabilityMaskedGatherScatterINTEL: return "MaskedGatherScatterINTEL"; - case CapabilityCacheControlsINTEL: return "CacheControlsINTEL"; - case CapabilityRegisterLimitsINTEL: return "RegisterLimitsINTEL"; - default: return "Unknown"; - } -} - -inline const char* RayQueryIntersectionToString(RayQueryIntersection value) { - switch (value) { - case RayQueryIntersectionRayQueryCandidateIntersectionKHR: return "RayQueryCandidateIntersectionKHR"; - case RayQueryIntersectionRayQueryCommittedIntersectionKHR: return "RayQueryCommittedIntersectionKHR"; - default: return "Unknown"; - } -} - -inline const char* RayQueryCommittedIntersectionTypeToString(RayQueryCommittedIntersectionType value) { - switch (value) { - case RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR: return "RayQueryCommittedIntersectionNoneKHR"; - case RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR: return "RayQueryCommittedIntersectionTriangleKHR"; - case RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR: return "RayQueryCommittedIntersectionGeneratedKHR"; - default: return "Unknown"; - } -} - -inline const char* RayQueryCandidateIntersectionTypeToString(RayQueryCandidateIntersectionType value) { - switch (value) { - case RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR: return "RayQueryCandidateIntersectionTriangleKHR"; - case RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR: return "RayQueryCandidateIntersectionAABBKHR"; - default: return "Unknown"; - } -} - -inline const char* FPDenormModeToString(FPDenormMode value) { - switch (value) { - case FPDenormModePreserve: return "Preserve"; - case FPDenormModeFlushToZero: return "FlushToZero"; - default: return "Unknown"; - } -} - -inline const char* FPOperationModeToString(FPOperationMode value) { - switch (value) { - case FPOperationModeIEEE: return "IEEE"; - case FPOperationModeALT: return "ALT"; - default: return "Unknown"; - } -} - -inline const char* QuantizationModesToString(QuantizationModes value) { - switch (value) { - case QuantizationModesTRN: return "TRN"; - case QuantizationModesTRN_ZERO: return "TRN_ZERO"; - case QuantizationModesRND: return "RND"; - case QuantizationModesRND_ZERO: return "RND_ZERO"; - case QuantizationModesRND_INF: return "RND_INF"; - case QuantizationModesRND_MIN_INF: return "RND_MIN_INF"; - case QuantizationModesRND_CONV: return "RND_CONV"; - case QuantizationModesRND_CONV_ODD: return "RND_CONV_ODD"; - default: return "Unknown"; - } -} - -inline const char* OverflowModesToString(OverflowModes value) { - switch (value) { - case OverflowModesWRAP: return "WRAP"; - case OverflowModesSAT: return "SAT"; - case OverflowModesSAT_ZERO: return "SAT_ZERO"; - case OverflowModesSAT_SYM: return "SAT_SYM"; - default: return "Unknown"; - } -} - -inline const char* PackedVectorFormatToString(PackedVectorFormat value) { - switch (value) { - case PackedVectorFormatPackedVectorFormat4x8Bit: return "PackedVectorFormat4x8Bit"; - default: return "Unknown"; - } -} - -inline const char* CooperativeMatrixLayoutToString(CooperativeMatrixLayout value) { - switch (value) { - case CooperativeMatrixLayoutRowMajorKHR: return "RowMajorKHR"; - case CooperativeMatrixLayoutColumnMajorKHR: return "ColumnMajorKHR"; - case CooperativeMatrixLayoutRowBlockedInterleavedARM: return "RowBlockedInterleavedARM"; - case CooperativeMatrixLayoutColumnBlockedInterleavedARM: return "ColumnBlockedInterleavedARM"; - default: return "Unknown"; - } -} - -inline const char* CooperativeMatrixUseToString(CooperativeMatrixUse value) { - switch (value) { - case CooperativeMatrixUseMatrixAKHR: return "MatrixAKHR"; - case CooperativeMatrixUseMatrixBKHR: return "MatrixBKHR"; - case CooperativeMatrixUseMatrixAccumulatorKHR: return "MatrixAccumulatorKHR"; - default: return "Unknown"; - } -} - -inline const char* TensorClampModeToString(TensorClampMode value) { - switch (value) { - case TensorClampModeUndefined: return "Undefined"; - case TensorClampModeConstant: return "Constant"; - case TensorClampModeClampToEdge: return "ClampToEdge"; - case TensorClampModeRepeat: return "Repeat"; - case TensorClampModeRepeatMirrored: return "RepeatMirrored"; - default: return "Unknown"; - } -} - -inline const char* InitializationModeQualifierToString(InitializationModeQualifier value) { - switch (value) { - case InitializationModeQualifierInitOnDeviceReprogramINTEL: return "InitOnDeviceReprogramINTEL"; - case InitializationModeQualifierInitOnDeviceResetINTEL: return "InitOnDeviceResetINTEL"; - default: return "Unknown"; - } -} - -inline const char* HostAccessQualifierToString(HostAccessQualifier value) { - switch (value) { - case HostAccessQualifierNoneINTEL: return "NoneINTEL"; - case HostAccessQualifierReadINTEL: return "ReadINTEL"; - case HostAccessQualifierWriteINTEL: return "WriteINTEL"; - case HostAccessQualifierReadWriteINTEL: return "ReadWriteINTEL"; - default: return "Unknown"; - } -} - -inline const char* LoadCacheControlToString(LoadCacheControl value) { - switch (value) { - case LoadCacheControlUncachedINTEL: return "UncachedINTEL"; - case LoadCacheControlCachedINTEL: return "CachedINTEL"; - case LoadCacheControlStreamingINTEL: return "StreamingINTEL"; - case LoadCacheControlInvalidateAfterReadINTEL: return "InvalidateAfterReadINTEL"; - case LoadCacheControlConstCachedINTEL: return "ConstCachedINTEL"; - default: return "Unknown"; - } -} - -inline const char* StoreCacheControlToString(StoreCacheControl value) { - switch (value) { - case StoreCacheControlUncachedINTEL: return "UncachedINTEL"; - case StoreCacheControlWriteThroughINTEL: return "WriteThroughINTEL"; - case StoreCacheControlWriteBackINTEL: return "WriteBackINTEL"; - case StoreCacheControlStreamingINTEL: return "StreamingINTEL"; - default: return "Unknown"; - } -} - -inline const char* NamedMaximumNumberOfRegistersToString(NamedMaximumNumberOfRegisters value) { - switch (value) { - case NamedMaximumNumberOfRegistersAutoINTEL: return "AutoINTEL"; - default: return "Unknown"; - } -} - -inline const char* FPEncodingToString(FPEncoding value) { - switch (value) { - default: return "Unknown"; - } -} - -inline const char* OpToString(Op value) { - switch (value) { - case OpNop: return "OpNop"; - case OpUndef: return "OpUndef"; - case OpSourceContinued: return "OpSourceContinued"; - case OpSource: return "OpSource"; - case OpSourceExtension: return "OpSourceExtension"; - case OpName: return "OpName"; - case OpMemberName: return "OpMemberName"; - case OpString: return "OpString"; - case OpLine: return "OpLine"; - case OpExtension: return "OpExtension"; - case OpExtInstImport: return "OpExtInstImport"; - case OpExtInst: return "OpExtInst"; - case OpMemoryModel: return "OpMemoryModel"; - case OpEntryPoint: return "OpEntryPoint"; - case OpExecutionMode: return "OpExecutionMode"; - case OpCapability: return "OpCapability"; - case OpTypeVoid: return "OpTypeVoid"; - case OpTypeBool: return "OpTypeBool"; - case OpTypeInt: return "OpTypeInt"; - case OpTypeFloat: return "OpTypeFloat"; - case OpTypeVector: return "OpTypeVector"; - case OpTypeMatrix: return "OpTypeMatrix"; - case OpTypeImage: return "OpTypeImage"; - case OpTypeSampler: return "OpTypeSampler"; - case OpTypeSampledImage: return "OpTypeSampledImage"; - case OpTypeArray: return "OpTypeArray"; - case OpTypeRuntimeArray: return "OpTypeRuntimeArray"; - case OpTypeStruct: return "OpTypeStruct"; - case OpTypeOpaque: return "OpTypeOpaque"; - case OpTypePointer: return "OpTypePointer"; - case OpTypeFunction: return "OpTypeFunction"; - case OpTypeEvent: return "OpTypeEvent"; - case OpTypeDeviceEvent: return "OpTypeDeviceEvent"; - case OpTypeReserveId: return "OpTypeReserveId"; - case OpTypeQueue: return "OpTypeQueue"; - case OpTypePipe: return "OpTypePipe"; - case OpTypeForwardPointer: return "OpTypeForwardPointer"; - case OpConstantTrue: return "OpConstantTrue"; - case OpConstantFalse: return "OpConstantFalse"; - case OpConstant: return "OpConstant"; - case OpConstantComposite: return "OpConstantComposite"; - case OpConstantSampler: return "OpConstantSampler"; - case OpConstantNull: return "OpConstantNull"; - case OpSpecConstantTrue: return "OpSpecConstantTrue"; - case OpSpecConstantFalse: return "OpSpecConstantFalse"; - case OpSpecConstant: return "OpSpecConstant"; - case OpSpecConstantComposite: return "OpSpecConstantComposite"; - case OpSpecConstantOp: return "OpSpecConstantOp"; - case OpFunction: return "OpFunction"; - case OpFunctionParameter: return "OpFunctionParameter"; - case OpFunctionEnd: return "OpFunctionEnd"; - case OpFunctionCall: return "OpFunctionCall"; - case OpVariable: return "OpVariable"; - case OpImageTexelPointer: return "OpImageTexelPointer"; - case OpLoad: return "OpLoad"; - case OpStore: return "OpStore"; - case OpCopyMemory: return "OpCopyMemory"; - case OpCopyMemorySized: return "OpCopyMemorySized"; - case OpAccessChain: return "OpAccessChain"; - case OpInBoundsAccessChain: return "OpInBoundsAccessChain"; - case OpPtrAccessChain: return "OpPtrAccessChain"; - case OpArrayLength: return "OpArrayLength"; - case OpGenericPtrMemSemantics: return "OpGenericPtrMemSemantics"; - case OpInBoundsPtrAccessChain: return "OpInBoundsPtrAccessChain"; - case OpDecorate: return "OpDecorate"; - case OpMemberDecorate: return "OpMemberDecorate"; - case OpDecorationGroup: return "OpDecorationGroup"; - case OpGroupDecorate: return "OpGroupDecorate"; - case OpGroupMemberDecorate: return "OpGroupMemberDecorate"; - case OpVectorExtractDynamic: return "OpVectorExtractDynamic"; - case OpVectorInsertDynamic: return "OpVectorInsertDynamic"; - case OpVectorShuffle: return "OpVectorShuffle"; - case OpCompositeConstruct: return "OpCompositeConstruct"; - case OpCompositeExtract: return "OpCompositeExtract"; - case OpCompositeInsert: return "OpCompositeInsert"; - case OpCopyObject: return "OpCopyObject"; - case OpTranspose: return "OpTranspose"; - case OpSampledImage: return "OpSampledImage"; - case OpImageSampleImplicitLod: return "OpImageSampleImplicitLod"; - case OpImageSampleExplicitLod: return "OpImageSampleExplicitLod"; - case OpImageSampleDrefImplicitLod: return "OpImageSampleDrefImplicitLod"; - case OpImageSampleDrefExplicitLod: return "OpImageSampleDrefExplicitLod"; - case OpImageSampleProjImplicitLod: return "OpImageSampleProjImplicitLod"; - case OpImageSampleProjExplicitLod: return "OpImageSampleProjExplicitLod"; - case OpImageSampleProjDrefImplicitLod: return "OpImageSampleProjDrefImplicitLod"; - case OpImageSampleProjDrefExplicitLod: return "OpImageSampleProjDrefExplicitLod"; - case OpImageFetch: return "OpImageFetch"; - case OpImageGather: return "OpImageGather"; - case OpImageDrefGather: return "OpImageDrefGather"; - case OpImageRead: return "OpImageRead"; - case OpImageWrite: return "OpImageWrite"; - case OpImage: return "OpImage"; - case OpImageQueryFormat: return "OpImageQueryFormat"; - case OpImageQueryOrder: return "OpImageQueryOrder"; - case OpImageQuerySizeLod: return "OpImageQuerySizeLod"; - case OpImageQuerySize: return "OpImageQuerySize"; - case OpImageQueryLod: return "OpImageQueryLod"; - case OpImageQueryLevels: return "OpImageQueryLevels"; - case OpImageQuerySamples: return "OpImageQuerySamples"; - case OpConvertFToU: return "OpConvertFToU"; - case OpConvertFToS: return "OpConvertFToS"; - case OpConvertSToF: return "OpConvertSToF"; - case OpConvertUToF: return "OpConvertUToF"; - case OpUConvert: return "OpUConvert"; - case OpSConvert: return "OpSConvert"; - case OpFConvert: return "OpFConvert"; - case OpQuantizeToF16: return "OpQuantizeToF16"; - case OpConvertPtrToU: return "OpConvertPtrToU"; - case OpSatConvertSToU: return "OpSatConvertSToU"; - case OpSatConvertUToS: return "OpSatConvertUToS"; - case OpConvertUToPtr: return "OpConvertUToPtr"; - case OpPtrCastToGeneric: return "OpPtrCastToGeneric"; - case OpGenericCastToPtr: return "OpGenericCastToPtr"; - case OpGenericCastToPtrExplicit: return "OpGenericCastToPtrExplicit"; - case OpBitcast: return "OpBitcast"; - case OpSNegate: return "OpSNegate"; - case OpFNegate: return "OpFNegate"; - case OpIAdd: return "OpIAdd"; - case OpFAdd: return "OpFAdd"; - case OpISub: return "OpISub"; - case OpFSub: return "OpFSub"; - case OpIMul: return "OpIMul"; - case OpFMul: return "OpFMul"; - case OpUDiv: return "OpUDiv"; - case OpSDiv: return "OpSDiv"; - case OpFDiv: return "OpFDiv"; - case OpUMod: return "OpUMod"; - case OpSRem: return "OpSRem"; - case OpSMod: return "OpSMod"; - case OpFRem: return "OpFRem"; - case OpFMod: return "OpFMod"; - case OpVectorTimesScalar: return "OpVectorTimesScalar"; - case OpMatrixTimesScalar: return "OpMatrixTimesScalar"; - case OpVectorTimesMatrix: return "OpVectorTimesMatrix"; - case OpMatrixTimesVector: return "OpMatrixTimesVector"; - case OpMatrixTimesMatrix: return "OpMatrixTimesMatrix"; - case OpOuterProduct: return "OpOuterProduct"; - case OpDot: return "OpDot"; - case OpIAddCarry: return "OpIAddCarry"; - case OpISubBorrow: return "OpISubBorrow"; - case OpUMulExtended: return "OpUMulExtended"; - case OpSMulExtended: return "OpSMulExtended"; - case OpAny: return "OpAny"; - case OpAll: return "OpAll"; - case OpIsNan: return "OpIsNan"; - case OpIsInf: return "OpIsInf"; - case OpIsFinite: return "OpIsFinite"; - case OpIsNormal: return "OpIsNormal"; - case OpSignBitSet: return "OpSignBitSet"; - case OpLessOrGreater: return "OpLessOrGreater"; - case OpOrdered: return "OpOrdered"; - case OpUnordered: return "OpUnordered"; - case OpLogicalEqual: return "OpLogicalEqual"; - case OpLogicalNotEqual: return "OpLogicalNotEqual"; - case OpLogicalOr: return "OpLogicalOr"; - case OpLogicalAnd: return "OpLogicalAnd"; - case OpLogicalNot: return "OpLogicalNot"; - case OpSelect: return "OpSelect"; - case OpIEqual: return "OpIEqual"; - case OpINotEqual: return "OpINotEqual"; - case OpUGreaterThan: return "OpUGreaterThan"; - case OpSGreaterThan: return "OpSGreaterThan"; - case OpUGreaterThanEqual: return "OpUGreaterThanEqual"; - case OpSGreaterThanEqual: return "OpSGreaterThanEqual"; - case OpULessThan: return "OpULessThan"; - case OpSLessThan: return "OpSLessThan"; - case OpULessThanEqual: return "OpULessThanEqual"; - case OpSLessThanEqual: return "OpSLessThanEqual"; - case OpFOrdEqual: return "OpFOrdEqual"; - case OpFUnordEqual: return "OpFUnordEqual"; - case OpFOrdNotEqual: return "OpFOrdNotEqual"; - case OpFUnordNotEqual: return "OpFUnordNotEqual"; - case OpFOrdLessThan: return "OpFOrdLessThan"; - case OpFUnordLessThan: return "OpFUnordLessThan"; - case OpFOrdGreaterThan: return "OpFOrdGreaterThan"; - case OpFUnordGreaterThan: return "OpFUnordGreaterThan"; - case OpFOrdLessThanEqual: return "OpFOrdLessThanEqual"; - case OpFUnordLessThanEqual: return "OpFUnordLessThanEqual"; - case OpFOrdGreaterThanEqual: return "OpFOrdGreaterThanEqual"; - case OpFUnordGreaterThanEqual: return "OpFUnordGreaterThanEqual"; - case OpShiftRightLogical: return "OpShiftRightLogical"; - case OpShiftRightArithmetic: return "OpShiftRightArithmetic"; - case OpShiftLeftLogical: return "OpShiftLeftLogical"; - case OpBitwiseOr: return "OpBitwiseOr"; - case OpBitwiseXor: return "OpBitwiseXor"; - case OpBitwiseAnd: return "OpBitwiseAnd"; - case OpNot: return "OpNot"; - case OpBitFieldInsert: return "OpBitFieldInsert"; - case OpBitFieldSExtract: return "OpBitFieldSExtract"; - case OpBitFieldUExtract: return "OpBitFieldUExtract"; - case OpBitReverse: return "OpBitReverse"; - case OpBitCount: return "OpBitCount"; - case OpDPdx: return "OpDPdx"; - case OpDPdy: return "OpDPdy"; - case OpFwidth: return "OpFwidth"; - case OpDPdxFine: return "OpDPdxFine"; - case OpDPdyFine: return "OpDPdyFine"; - case OpFwidthFine: return "OpFwidthFine"; - case OpDPdxCoarse: return "OpDPdxCoarse"; - case OpDPdyCoarse: return "OpDPdyCoarse"; - case OpFwidthCoarse: return "OpFwidthCoarse"; - case OpEmitVertex: return "OpEmitVertex"; - case OpEndPrimitive: return "OpEndPrimitive"; - case OpEmitStreamVertex: return "OpEmitStreamVertex"; - case OpEndStreamPrimitive: return "OpEndStreamPrimitive"; - case OpControlBarrier: return "OpControlBarrier"; - case OpMemoryBarrier: return "OpMemoryBarrier"; - case OpAtomicLoad: return "OpAtomicLoad"; - case OpAtomicStore: return "OpAtomicStore"; - case OpAtomicExchange: return "OpAtomicExchange"; - case OpAtomicCompareExchange: return "OpAtomicCompareExchange"; - case OpAtomicCompareExchangeWeak: return "OpAtomicCompareExchangeWeak"; - case OpAtomicIIncrement: return "OpAtomicIIncrement"; - case OpAtomicIDecrement: return "OpAtomicIDecrement"; - case OpAtomicIAdd: return "OpAtomicIAdd"; - case OpAtomicISub: return "OpAtomicISub"; - case OpAtomicSMin: return "OpAtomicSMin"; - case OpAtomicUMin: return "OpAtomicUMin"; - case OpAtomicSMax: return "OpAtomicSMax"; - case OpAtomicUMax: return "OpAtomicUMax"; - case OpAtomicAnd: return "OpAtomicAnd"; - case OpAtomicOr: return "OpAtomicOr"; - case OpAtomicXor: return "OpAtomicXor"; - case OpPhi: return "OpPhi"; - case OpLoopMerge: return "OpLoopMerge"; - case OpSelectionMerge: return "OpSelectionMerge"; - case OpLabel: return "OpLabel"; - case OpBranch: return "OpBranch"; - case OpBranchConditional: return "OpBranchConditional"; - case OpSwitch: return "OpSwitch"; - case OpKill: return "OpKill"; - case OpReturn: return "OpReturn"; - case OpReturnValue: return "OpReturnValue"; - case OpUnreachable: return "OpUnreachable"; - case OpLifetimeStart: return "OpLifetimeStart"; - case OpLifetimeStop: return "OpLifetimeStop"; - case OpGroupAsyncCopy: return "OpGroupAsyncCopy"; - case OpGroupWaitEvents: return "OpGroupWaitEvents"; - case OpGroupAll: return "OpGroupAll"; - case OpGroupAny: return "OpGroupAny"; - case OpGroupBroadcast: return "OpGroupBroadcast"; - case OpGroupIAdd: return "OpGroupIAdd"; - case OpGroupFAdd: return "OpGroupFAdd"; - case OpGroupFMin: return "OpGroupFMin"; - case OpGroupUMin: return "OpGroupUMin"; - case OpGroupSMin: return "OpGroupSMin"; - case OpGroupFMax: return "OpGroupFMax"; - case OpGroupUMax: return "OpGroupUMax"; - case OpGroupSMax: return "OpGroupSMax"; - case OpReadPipe: return "OpReadPipe"; - case OpWritePipe: return "OpWritePipe"; - case OpReservedReadPipe: return "OpReservedReadPipe"; - case OpReservedWritePipe: return "OpReservedWritePipe"; - case OpReserveReadPipePackets: return "OpReserveReadPipePackets"; - case OpReserveWritePipePackets: return "OpReserveWritePipePackets"; - case OpCommitReadPipe: return "OpCommitReadPipe"; - case OpCommitWritePipe: return "OpCommitWritePipe"; - case OpIsValidReserveId: return "OpIsValidReserveId"; - case OpGetNumPipePackets: return "OpGetNumPipePackets"; - case OpGetMaxPipePackets: return "OpGetMaxPipePackets"; - case OpGroupReserveReadPipePackets: return "OpGroupReserveReadPipePackets"; - case OpGroupReserveWritePipePackets: return "OpGroupReserveWritePipePackets"; - case OpGroupCommitReadPipe: return "OpGroupCommitReadPipe"; - case OpGroupCommitWritePipe: return "OpGroupCommitWritePipe"; - case OpEnqueueMarker: return "OpEnqueueMarker"; - case OpEnqueueKernel: return "OpEnqueueKernel"; - case OpGetKernelNDrangeSubGroupCount: return "OpGetKernelNDrangeSubGroupCount"; - case OpGetKernelNDrangeMaxSubGroupSize: return "OpGetKernelNDrangeMaxSubGroupSize"; - case OpGetKernelWorkGroupSize: return "OpGetKernelWorkGroupSize"; - case OpGetKernelPreferredWorkGroupSizeMultiple: return "OpGetKernelPreferredWorkGroupSizeMultiple"; - case OpRetainEvent: return "OpRetainEvent"; - case OpReleaseEvent: return "OpReleaseEvent"; - case OpCreateUserEvent: return "OpCreateUserEvent"; - case OpIsValidEvent: return "OpIsValidEvent"; - case OpSetUserEventStatus: return "OpSetUserEventStatus"; - case OpCaptureEventProfilingInfo: return "OpCaptureEventProfilingInfo"; - case OpGetDefaultQueue: return "OpGetDefaultQueue"; - case OpBuildNDRange: return "OpBuildNDRange"; - case OpImageSparseSampleImplicitLod: return "OpImageSparseSampleImplicitLod"; - case OpImageSparseSampleExplicitLod: return "OpImageSparseSampleExplicitLod"; - case OpImageSparseSampleDrefImplicitLod: return "OpImageSparseSampleDrefImplicitLod"; - case OpImageSparseSampleDrefExplicitLod: return "OpImageSparseSampleDrefExplicitLod"; - case OpImageSparseSampleProjImplicitLod: return "OpImageSparseSampleProjImplicitLod"; - case OpImageSparseSampleProjExplicitLod: return "OpImageSparseSampleProjExplicitLod"; - case OpImageSparseSampleProjDrefImplicitLod: return "OpImageSparseSampleProjDrefImplicitLod"; - case OpImageSparseSampleProjDrefExplicitLod: return "OpImageSparseSampleProjDrefExplicitLod"; - case OpImageSparseFetch: return "OpImageSparseFetch"; - case OpImageSparseGather: return "OpImageSparseGather"; - case OpImageSparseDrefGather: return "OpImageSparseDrefGather"; - case OpImageSparseTexelsResident: return "OpImageSparseTexelsResident"; - case OpNoLine: return "OpNoLine"; - case OpAtomicFlagTestAndSet: return "OpAtomicFlagTestAndSet"; - case OpAtomicFlagClear: return "OpAtomicFlagClear"; - case OpImageSparseRead: return "OpImageSparseRead"; - case OpSizeOf: return "OpSizeOf"; - case OpTypePipeStorage: return "OpTypePipeStorage"; - case OpConstantPipeStorage: return "OpConstantPipeStorage"; - case OpCreatePipeFromPipeStorage: return "OpCreatePipeFromPipeStorage"; - case OpGetKernelLocalSizeForSubgroupCount: return "OpGetKernelLocalSizeForSubgroupCount"; - case OpGetKernelMaxNumSubgroups: return "OpGetKernelMaxNumSubgroups"; - case OpTypeNamedBarrier: return "OpTypeNamedBarrier"; - case OpNamedBarrierInitialize: return "OpNamedBarrierInitialize"; - case OpMemoryNamedBarrier: return "OpMemoryNamedBarrier"; - case OpModuleProcessed: return "OpModuleProcessed"; - case OpExecutionModeId: return "OpExecutionModeId"; - case OpDecorateId: return "OpDecorateId"; - case OpGroupNonUniformElect: return "OpGroupNonUniformElect"; - case OpGroupNonUniformAll: return "OpGroupNonUniformAll"; - case OpGroupNonUniformAny: return "OpGroupNonUniformAny"; - case OpGroupNonUniformAllEqual: return "OpGroupNonUniformAllEqual"; - case OpGroupNonUniformBroadcast: return "OpGroupNonUniformBroadcast"; - case OpGroupNonUniformBroadcastFirst: return "OpGroupNonUniformBroadcastFirst"; - case OpGroupNonUniformBallot: return "OpGroupNonUniformBallot"; - case OpGroupNonUniformInverseBallot: return "OpGroupNonUniformInverseBallot"; - case OpGroupNonUniformBallotBitExtract: return "OpGroupNonUniformBallotBitExtract"; - case OpGroupNonUniformBallotBitCount: return "OpGroupNonUniformBallotBitCount"; - case OpGroupNonUniformBallotFindLSB: return "OpGroupNonUniformBallotFindLSB"; - case OpGroupNonUniformBallotFindMSB: return "OpGroupNonUniformBallotFindMSB"; - case OpGroupNonUniformShuffle: return "OpGroupNonUniformShuffle"; - case OpGroupNonUniformShuffleXor: return "OpGroupNonUniformShuffleXor"; - case OpGroupNonUniformShuffleUp: return "OpGroupNonUniformShuffleUp"; - case OpGroupNonUniformShuffleDown: return "OpGroupNonUniformShuffleDown"; - case OpGroupNonUniformIAdd: return "OpGroupNonUniformIAdd"; - case OpGroupNonUniformFAdd: return "OpGroupNonUniformFAdd"; - case OpGroupNonUniformIMul: return "OpGroupNonUniformIMul"; - case OpGroupNonUniformFMul: return "OpGroupNonUniformFMul"; - case OpGroupNonUniformSMin: return "OpGroupNonUniformSMin"; - case OpGroupNonUniformUMin: return "OpGroupNonUniformUMin"; - case OpGroupNonUniformFMin: return "OpGroupNonUniformFMin"; - case OpGroupNonUniformSMax: return "OpGroupNonUniformSMax"; - case OpGroupNonUniformUMax: return "OpGroupNonUniformUMax"; - case OpGroupNonUniformFMax: return "OpGroupNonUniformFMax"; - case OpGroupNonUniformBitwiseAnd: return "OpGroupNonUniformBitwiseAnd"; - case OpGroupNonUniformBitwiseOr: return "OpGroupNonUniformBitwiseOr"; - case OpGroupNonUniformBitwiseXor: return "OpGroupNonUniformBitwiseXor"; - case OpGroupNonUniformLogicalAnd: return "OpGroupNonUniformLogicalAnd"; - case OpGroupNonUniformLogicalOr: return "OpGroupNonUniformLogicalOr"; - case OpGroupNonUniformLogicalXor: return "OpGroupNonUniformLogicalXor"; - case OpGroupNonUniformQuadBroadcast: return "OpGroupNonUniformQuadBroadcast"; - case OpGroupNonUniformQuadSwap: return "OpGroupNonUniformQuadSwap"; - case OpCopyLogical: return "OpCopyLogical"; - case OpPtrEqual: return "OpPtrEqual"; - case OpPtrNotEqual: return "OpPtrNotEqual"; - case OpPtrDiff: return "OpPtrDiff"; - case OpColorAttachmentReadEXT: return "OpColorAttachmentReadEXT"; - case OpDepthAttachmentReadEXT: return "OpDepthAttachmentReadEXT"; - case OpStencilAttachmentReadEXT: return "OpStencilAttachmentReadEXT"; - case OpTerminateInvocation: return "OpTerminateInvocation"; - case OpTypeUntypedPointerKHR: return "OpTypeUntypedPointerKHR"; - case OpUntypedVariableKHR: return "OpUntypedVariableKHR"; - case OpUntypedAccessChainKHR: return "OpUntypedAccessChainKHR"; - case OpUntypedInBoundsAccessChainKHR: return "OpUntypedInBoundsAccessChainKHR"; - case OpSubgroupBallotKHR: return "OpSubgroupBallotKHR"; - case OpSubgroupFirstInvocationKHR: return "OpSubgroupFirstInvocationKHR"; - case OpUntypedPtrAccessChainKHR: return "OpUntypedPtrAccessChainKHR"; - case OpUntypedInBoundsPtrAccessChainKHR: return "OpUntypedInBoundsPtrAccessChainKHR"; - case OpUntypedArrayLengthKHR: return "OpUntypedArrayLengthKHR"; - case OpUntypedPrefetchKHR: return "OpUntypedPrefetchKHR"; - case OpSubgroupAllKHR: return "OpSubgroupAllKHR"; - case OpSubgroupAnyKHR: return "OpSubgroupAnyKHR"; - case OpSubgroupAllEqualKHR: return "OpSubgroupAllEqualKHR"; - case OpGroupNonUniformRotateKHR: return "OpGroupNonUniformRotateKHR"; - case OpSubgroupReadInvocationKHR: return "OpSubgroupReadInvocationKHR"; - case OpExtInstWithForwardRefsKHR: return "OpExtInstWithForwardRefsKHR"; - case OpTraceRayKHR: return "OpTraceRayKHR"; - case OpExecuteCallableKHR: return "OpExecuteCallableKHR"; - case OpConvertUToAccelerationStructureKHR: return "OpConvertUToAccelerationStructureKHR"; - case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR"; - case OpTerminateRayKHR: return "OpTerminateRayKHR"; - case OpSDot: return "OpSDot"; - case OpUDot: return "OpUDot"; - case OpSUDot: return "OpSUDot"; - case OpSDotAccSat: return "OpSDotAccSat"; - case OpUDotAccSat: return "OpUDotAccSat"; - case OpSUDotAccSat: return "OpSUDotAccSat"; - case OpTypeCooperativeMatrixKHR: return "OpTypeCooperativeMatrixKHR"; - case OpCooperativeMatrixLoadKHR: return "OpCooperativeMatrixLoadKHR"; - case OpCooperativeMatrixStoreKHR: return "OpCooperativeMatrixStoreKHR"; - case OpCooperativeMatrixMulAddKHR: return "OpCooperativeMatrixMulAddKHR"; - case OpCooperativeMatrixLengthKHR: return "OpCooperativeMatrixLengthKHR"; - case OpConstantCompositeReplicateEXT: return "OpConstantCompositeReplicateEXT"; - case OpSpecConstantCompositeReplicateEXT: return "OpSpecConstantCompositeReplicateEXT"; - case OpCompositeConstructReplicateEXT: return "OpCompositeConstructReplicateEXT"; - case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR"; - case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR"; - case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR"; - case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR"; - case OpRayQueryConfirmIntersectionKHR: return "OpRayQueryConfirmIntersectionKHR"; - case OpRayQueryProceedKHR: return "OpRayQueryProceedKHR"; - case OpRayQueryGetIntersectionTypeKHR: return "OpRayQueryGetIntersectionTypeKHR"; - case OpImageSampleWeightedQCOM: return "OpImageSampleWeightedQCOM"; - case OpImageBoxFilterQCOM: return "OpImageBoxFilterQCOM"; - case OpImageBlockMatchSSDQCOM: return "OpImageBlockMatchSSDQCOM"; - case OpImageBlockMatchSADQCOM: return "OpImageBlockMatchSADQCOM"; - case OpImageBlockMatchWindowSSDQCOM: return "OpImageBlockMatchWindowSSDQCOM"; - case OpImageBlockMatchWindowSADQCOM: return "OpImageBlockMatchWindowSADQCOM"; - case OpImageBlockMatchGatherSSDQCOM: return "OpImageBlockMatchGatherSSDQCOM"; - case OpImageBlockMatchGatherSADQCOM: return "OpImageBlockMatchGatherSADQCOM"; - case OpGroupIAddNonUniformAMD: return "OpGroupIAddNonUniformAMD"; - case OpGroupFAddNonUniformAMD: return "OpGroupFAddNonUniformAMD"; - case OpGroupFMinNonUniformAMD: return "OpGroupFMinNonUniformAMD"; - case OpGroupUMinNonUniformAMD: return "OpGroupUMinNonUniformAMD"; - case OpGroupSMinNonUniformAMD: return "OpGroupSMinNonUniformAMD"; - case OpGroupFMaxNonUniformAMD: return "OpGroupFMaxNonUniformAMD"; - case OpGroupUMaxNonUniformAMD: return "OpGroupUMaxNonUniformAMD"; - case OpGroupSMaxNonUniformAMD: return "OpGroupSMaxNonUniformAMD"; - case OpFragmentMaskFetchAMD: return "OpFragmentMaskFetchAMD"; - case OpFragmentFetchAMD: return "OpFragmentFetchAMD"; - case OpReadClockKHR: return "OpReadClockKHR"; - case OpAllocateNodePayloadsAMDX: return "OpAllocateNodePayloadsAMDX"; - case OpEnqueueNodePayloadsAMDX: return "OpEnqueueNodePayloadsAMDX"; - case OpTypeNodePayloadArrayAMDX: return "OpTypeNodePayloadArrayAMDX"; - case OpFinishWritingNodePayloadAMDX: return "OpFinishWritingNodePayloadAMDX"; - case OpNodePayloadArrayLengthAMDX: return "OpNodePayloadArrayLengthAMDX"; - case OpIsNodePayloadValidAMDX: return "OpIsNodePayloadValidAMDX"; - case OpConstantStringAMDX: return "OpConstantStringAMDX"; - case OpSpecConstantStringAMDX: return "OpSpecConstantStringAMDX"; - case OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR"; - case OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR"; - case OpHitObjectRecordHitMotionNV: return "OpHitObjectRecordHitMotionNV"; - case OpHitObjectRecordHitWithIndexMotionNV: return "OpHitObjectRecordHitWithIndexMotionNV"; - case OpHitObjectRecordMissMotionNV: return "OpHitObjectRecordMissMotionNV"; - case OpHitObjectGetWorldToObjectNV: return "OpHitObjectGetWorldToObjectNV"; - case OpHitObjectGetObjectToWorldNV: return "OpHitObjectGetObjectToWorldNV"; - case OpHitObjectGetObjectRayDirectionNV: return "OpHitObjectGetObjectRayDirectionNV"; - case OpHitObjectGetObjectRayOriginNV: return "OpHitObjectGetObjectRayOriginNV"; - case OpHitObjectTraceRayMotionNV: return "OpHitObjectTraceRayMotionNV"; - case OpHitObjectGetShaderRecordBufferHandleNV: return "OpHitObjectGetShaderRecordBufferHandleNV"; - case OpHitObjectGetShaderBindingTableRecordIndexNV: return "OpHitObjectGetShaderBindingTableRecordIndexNV"; - case OpHitObjectRecordEmptyNV: return "OpHitObjectRecordEmptyNV"; - case OpHitObjectTraceRayNV: return "OpHitObjectTraceRayNV"; - case OpHitObjectRecordHitNV: return "OpHitObjectRecordHitNV"; - case OpHitObjectRecordHitWithIndexNV: return "OpHitObjectRecordHitWithIndexNV"; - case OpHitObjectRecordMissNV: return "OpHitObjectRecordMissNV"; - case OpHitObjectExecuteShaderNV: return "OpHitObjectExecuteShaderNV"; - case OpHitObjectGetCurrentTimeNV: return "OpHitObjectGetCurrentTimeNV"; - case OpHitObjectGetAttributesNV: return "OpHitObjectGetAttributesNV"; - case OpHitObjectGetHitKindNV: return "OpHitObjectGetHitKindNV"; - case OpHitObjectGetPrimitiveIndexNV: return "OpHitObjectGetPrimitiveIndexNV"; - case OpHitObjectGetGeometryIndexNV: return "OpHitObjectGetGeometryIndexNV"; - case OpHitObjectGetInstanceIdNV: return "OpHitObjectGetInstanceIdNV"; - case OpHitObjectGetInstanceCustomIndexNV: return "OpHitObjectGetInstanceCustomIndexNV"; - case OpHitObjectGetWorldRayDirectionNV: return "OpHitObjectGetWorldRayDirectionNV"; - case OpHitObjectGetWorldRayOriginNV: return "OpHitObjectGetWorldRayOriginNV"; - case OpHitObjectGetRayTMaxNV: return "OpHitObjectGetRayTMaxNV"; - case OpHitObjectGetRayTMinNV: return "OpHitObjectGetRayTMinNV"; - case OpHitObjectIsEmptyNV: return "OpHitObjectIsEmptyNV"; - case OpHitObjectIsHitNV: return "OpHitObjectIsHitNV"; - case OpHitObjectIsMissNV: return "OpHitObjectIsMissNV"; - case OpReorderThreadWithHitObjectNV: return "OpReorderThreadWithHitObjectNV"; - case OpReorderThreadWithHintNV: return "OpReorderThreadWithHintNV"; - case OpTypeHitObjectNV: return "OpTypeHitObjectNV"; - case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV"; - case OpCooperativeMatrixConvertNV: return "OpCooperativeMatrixConvertNV"; - case OpEmitMeshTasksEXT: return "OpEmitMeshTasksEXT"; - case OpSetMeshOutputsEXT: return "OpSetMeshOutputsEXT"; - case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV"; - case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV"; - case OpFetchMicroTriangleVertexPositionNV: return "OpFetchMicroTriangleVertexPositionNV"; - case OpFetchMicroTriangleVertexBarycentricNV: return "OpFetchMicroTriangleVertexBarycentricNV"; - case OpReportIntersectionKHR: return "OpReportIntersectionKHR"; - case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV"; - case OpTerminateRayNV: return "OpTerminateRayNV"; - case OpTraceNV: return "OpTraceNV"; - case OpTraceMotionNV: return "OpTraceMotionNV"; - case OpTraceRayMotionNV: return "OpTraceRayMotionNV"; - case OpRayQueryGetIntersectionTriangleVertexPositionsKHR: return "OpRayQueryGetIntersectionTriangleVertexPositionsKHR"; - case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR"; - case OpExecuteCallableNV: return "OpExecuteCallableNV"; - case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV"; - case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV"; - case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV"; - case OpCooperativeMatrixMulAddNV: return "OpCooperativeMatrixMulAddNV"; - case OpCooperativeMatrixLengthNV: return "OpCooperativeMatrixLengthNV"; - case OpBeginInvocationInterlockEXT: return "OpBeginInvocationInterlockEXT"; - case OpEndInvocationInterlockEXT: return "OpEndInvocationInterlockEXT"; - case OpCooperativeMatrixReduceNV: return "OpCooperativeMatrixReduceNV"; - case OpCooperativeMatrixLoadTensorNV: return "OpCooperativeMatrixLoadTensorNV"; - case OpCooperativeMatrixStoreTensorNV: return "OpCooperativeMatrixStoreTensorNV"; - case OpCooperativeMatrixPerElementOpNV: return "OpCooperativeMatrixPerElementOpNV"; - case OpTypeTensorLayoutNV: return "OpTypeTensorLayoutNV"; - case OpTypeTensorViewNV: return "OpTypeTensorViewNV"; - case OpCreateTensorLayoutNV: return "OpCreateTensorLayoutNV"; - case OpTensorLayoutSetDimensionNV: return "OpTensorLayoutSetDimensionNV"; - case OpTensorLayoutSetStrideNV: return "OpTensorLayoutSetStrideNV"; - case OpTensorLayoutSliceNV: return "OpTensorLayoutSliceNV"; - case OpTensorLayoutSetClampValueNV: return "OpTensorLayoutSetClampValueNV"; - case OpCreateTensorViewNV: return "OpCreateTensorViewNV"; - case OpTensorViewSetDimensionNV: return "OpTensorViewSetDimensionNV"; - case OpTensorViewSetStrideNV: return "OpTensorViewSetStrideNV"; - case OpDemoteToHelperInvocation: return "OpDemoteToHelperInvocation"; - case OpIsHelperInvocationEXT: return "OpIsHelperInvocationEXT"; - case OpTensorViewSetClipNV: return "OpTensorViewSetClipNV"; - case OpTensorLayoutSetBlockSizeNV: return "OpTensorLayoutSetBlockSizeNV"; - case OpCooperativeMatrixTransposeNV: return "OpCooperativeMatrixTransposeNV"; - case OpConvertUToImageNV: return "OpConvertUToImageNV"; - case OpConvertUToSamplerNV: return "OpConvertUToSamplerNV"; - case OpConvertImageToUNV: return "OpConvertImageToUNV"; - case OpConvertSamplerToUNV: return "OpConvertSamplerToUNV"; - case OpConvertUToSampledImageNV: return "OpConvertUToSampledImageNV"; - case OpConvertSampledImageToUNV: return "OpConvertSampledImageToUNV"; - case OpSamplerImageAddressingModeNV: return "OpSamplerImageAddressingModeNV"; - case OpRawAccessChainNV: return "OpRawAccessChainNV"; - case OpSubgroupShuffleINTEL: return "OpSubgroupShuffleINTEL"; - case OpSubgroupShuffleDownINTEL: return "OpSubgroupShuffleDownINTEL"; - case OpSubgroupShuffleUpINTEL: return "OpSubgroupShuffleUpINTEL"; - case OpSubgroupShuffleXorINTEL: return "OpSubgroupShuffleXorINTEL"; - case OpSubgroupBlockReadINTEL: return "OpSubgroupBlockReadINTEL"; - case OpSubgroupBlockWriteINTEL: return "OpSubgroupBlockWriteINTEL"; - case OpSubgroupImageBlockReadINTEL: return "OpSubgroupImageBlockReadINTEL"; - case OpSubgroupImageBlockWriteINTEL: return "OpSubgroupImageBlockWriteINTEL"; - case OpSubgroupImageMediaBlockReadINTEL: return "OpSubgroupImageMediaBlockReadINTEL"; - case OpSubgroupImageMediaBlockWriteINTEL: return "OpSubgroupImageMediaBlockWriteINTEL"; - case OpUCountLeadingZerosINTEL: return "OpUCountLeadingZerosINTEL"; - case OpUCountTrailingZerosINTEL: return "OpUCountTrailingZerosINTEL"; - case OpAbsISubINTEL: return "OpAbsISubINTEL"; - case OpAbsUSubINTEL: return "OpAbsUSubINTEL"; - case OpIAddSatINTEL: return "OpIAddSatINTEL"; - case OpUAddSatINTEL: return "OpUAddSatINTEL"; - case OpIAverageINTEL: return "OpIAverageINTEL"; - case OpUAverageINTEL: return "OpUAverageINTEL"; - case OpIAverageRoundedINTEL: return "OpIAverageRoundedINTEL"; - case OpUAverageRoundedINTEL: return "OpUAverageRoundedINTEL"; - case OpISubSatINTEL: return "OpISubSatINTEL"; - case OpUSubSatINTEL: return "OpUSubSatINTEL"; - case OpIMul32x16INTEL: return "OpIMul32x16INTEL"; - case OpUMul32x16INTEL: return "OpUMul32x16INTEL"; - case OpConstantFunctionPointerINTEL: return "OpConstantFunctionPointerINTEL"; - case OpFunctionPointerCallINTEL: return "OpFunctionPointerCallINTEL"; - case OpAsmTargetINTEL: return "OpAsmTargetINTEL"; - case OpAsmINTEL: return "OpAsmINTEL"; - case OpAsmCallINTEL: return "OpAsmCallINTEL"; - case OpAtomicFMinEXT: return "OpAtomicFMinEXT"; - case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT"; - case OpAssumeTrueKHR: return "OpAssumeTrueKHR"; - case OpExpectKHR: return "OpExpectKHR"; - case OpDecorateString: return "OpDecorateString"; - case OpMemberDecorateString: return "OpMemberDecorateString"; - case OpVmeImageINTEL: return "OpVmeImageINTEL"; - case OpTypeVmeImageINTEL: return "OpTypeVmeImageINTEL"; - case OpTypeAvcImePayloadINTEL: return "OpTypeAvcImePayloadINTEL"; - case OpTypeAvcRefPayloadINTEL: return "OpTypeAvcRefPayloadINTEL"; - case OpTypeAvcSicPayloadINTEL: return "OpTypeAvcSicPayloadINTEL"; - case OpTypeAvcMcePayloadINTEL: return "OpTypeAvcMcePayloadINTEL"; - case OpTypeAvcMceResultINTEL: return "OpTypeAvcMceResultINTEL"; - case OpTypeAvcImeResultINTEL: return "OpTypeAvcImeResultINTEL"; - case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: return "OpTypeAvcImeResultSingleReferenceStreamoutINTEL"; - case OpTypeAvcImeResultDualReferenceStreamoutINTEL: return "OpTypeAvcImeResultDualReferenceStreamoutINTEL"; - case OpTypeAvcImeSingleReferenceStreaminINTEL: return "OpTypeAvcImeSingleReferenceStreaminINTEL"; - case OpTypeAvcImeDualReferenceStreaminINTEL: return "OpTypeAvcImeDualReferenceStreaminINTEL"; - case OpTypeAvcRefResultINTEL: return "OpTypeAvcRefResultINTEL"; - case OpTypeAvcSicResultINTEL: return "OpTypeAvcSicResultINTEL"; - case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: return "OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL"; - case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: return "OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL"; - case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: return "OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL"; - case OpSubgroupAvcMceSetInterShapePenaltyINTEL: return "OpSubgroupAvcMceSetInterShapePenaltyINTEL"; - case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: return "OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL"; - case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: return "OpSubgroupAvcMceSetInterDirectionPenaltyINTEL"; - case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: return "OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL"; - case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: return "OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL"; - case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: return "OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL"; - case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: return "OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL"; - case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: return "OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL"; - case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: return "OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL"; - case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: return "OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL"; - case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: return "OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL"; - case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: return "OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL"; - case OpSubgroupAvcMceSetAcOnlyHaarINTEL: return "OpSubgroupAvcMceSetAcOnlyHaarINTEL"; - case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: return "OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL"; - case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: return "OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL"; - case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: return "OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL"; - case OpSubgroupAvcMceConvertToImePayloadINTEL: return "OpSubgroupAvcMceConvertToImePayloadINTEL"; - case OpSubgroupAvcMceConvertToImeResultINTEL: return "OpSubgroupAvcMceConvertToImeResultINTEL"; - case OpSubgroupAvcMceConvertToRefPayloadINTEL: return "OpSubgroupAvcMceConvertToRefPayloadINTEL"; - case OpSubgroupAvcMceConvertToRefResultINTEL: return "OpSubgroupAvcMceConvertToRefResultINTEL"; - case OpSubgroupAvcMceConvertToSicPayloadINTEL: return "OpSubgroupAvcMceConvertToSicPayloadINTEL"; - case OpSubgroupAvcMceConvertToSicResultINTEL: return "OpSubgroupAvcMceConvertToSicResultINTEL"; - case OpSubgroupAvcMceGetMotionVectorsINTEL: return "OpSubgroupAvcMceGetMotionVectorsINTEL"; - case OpSubgroupAvcMceGetInterDistortionsINTEL: return "OpSubgroupAvcMceGetInterDistortionsINTEL"; - case OpSubgroupAvcMceGetBestInterDistortionsINTEL: return "OpSubgroupAvcMceGetBestInterDistortionsINTEL"; - case OpSubgroupAvcMceGetInterMajorShapeINTEL: return "OpSubgroupAvcMceGetInterMajorShapeINTEL"; - case OpSubgroupAvcMceGetInterMinorShapeINTEL: return "OpSubgroupAvcMceGetInterMinorShapeINTEL"; - case OpSubgroupAvcMceGetInterDirectionsINTEL: return "OpSubgroupAvcMceGetInterDirectionsINTEL"; - case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: return "OpSubgroupAvcMceGetInterMotionVectorCountINTEL"; - case OpSubgroupAvcMceGetInterReferenceIdsINTEL: return "OpSubgroupAvcMceGetInterReferenceIdsINTEL"; - case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: return "OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL"; - case OpSubgroupAvcImeInitializeINTEL: return "OpSubgroupAvcImeInitializeINTEL"; - case OpSubgroupAvcImeSetSingleReferenceINTEL: return "OpSubgroupAvcImeSetSingleReferenceINTEL"; - case OpSubgroupAvcImeSetDualReferenceINTEL: return "OpSubgroupAvcImeSetDualReferenceINTEL"; - case OpSubgroupAvcImeRefWindowSizeINTEL: return "OpSubgroupAvcImeRefWindowSizeINTEL"; - case OpSubgroupAvcImeAdjustRefOffsetINTEL: return "OpSubgroupAvcImeAdjustRefOffsetINTEL"; - case OpSubgroupAvcImeConvertToMcePayloadINTEL: return "OpSubgroupAvcImeConvertToMcePayloadINTEL"; - case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: return "OpSubgroupAvcImeSetMaxMotionVectorCountINTEL"; - case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: return "OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL"; - case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: return "OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL"; - case OpSubgroupAvcImeSetWeightedSadINTEL: return "OpSubgroupAvcImeSetWeightedSadINTEL"; - case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: return "OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL"; - case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: return "OpSubgroupAvcImeEvaluateWithDualReferenceINTEL"; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: return "OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL"; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: return "OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL"; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: return "OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL"; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: return "OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL"; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: return "OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL"; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: return "OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL"; - case OpSubgroupAvcImeConvertToMceResultINTEL: return "OpSubgroupAvcImeConvertToMceResultINTEL"; - case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: return "OpSubgroupAvcImeGetSingleReferenceStreaminINTEL"; - case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: return "OpSubgroupAvcImeGetDualReferenceStreaminINTEL"; - case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: return "OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL"; - case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: return "OpSubgroupAvcImeStripDualReferenceStreamoutINTEL"; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: return "OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL"; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: return "OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL"; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: return "OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL"; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: return "OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL"; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: return "OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL"; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: return "OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL"; - case OpSubgroupAvcImeGetBorderReachedINTEL: return "OpSubgroupAvcImeGetBorderReachedINTEL"; - case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: return "OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL"; - case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: return "OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL"; - case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: return "OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL"; - case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: return "OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL"; - case OpSubgroupAvcFmeInitializeINTEL: return "OpSubgroupAvcFmeInitializeINTEL"; - case OpSubgroupAvcBmeInitializeINTEL: return "OpSubgroupAvcBmeInitializeINTEL"; - case OpSubgroupAvcRefConvertToMcePayloadINTEL: return "OpSubgroupAvcRefConvertToMcePayloadINTEL"; - case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: return "OpSubgroupAvcRefSetBidirectionalMixDisableINTEL"; - case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: return "OpSubgroupAvcRefSetBilinearFilterEnableINTEL"; - case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: return "OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL"; - case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: return "OpSubgroupAvcRefEvaluateWithDualReferenceINTEL"; - case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: return "OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL"; - case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: return "OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL"; - case OpSubgroupAvcRefConvertToMceResultINTEL: return "OpSubgroupAvcRefConvertToMceResultINTEL"; - case OpSubgroupAvcSicInitializeINTEL: return "OpSubgroupAvcSicInitializeINTEL"; - case OpSubgroupAvcSicConfigureSkcINTEL: return "OpSubgroupAvcSicConfigureSkcINTEL"; - case OpSubgroupAvcSicConfigureIpeLumaINTEL: return "OpSubgroupAvcSicConfigureIpeLumaINTEL"; - case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: return "OpSubgroupAvcSicConfigureIpeLumaChromaINTEL"; - case OpSubgroupAvcSicGetMotionVectorMaskINTEL: return "OpSubgroupAvcSicGetMotionVectorMaskINTEL"; - case OpSubgroupAvcSicConvertToMcePayloadINTEL: return "OpSubgroupAvcSicConvertToMcePayloadINTEL"; - case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: return "OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL"; - case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: return "OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL"; - case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: return "OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL"; - case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: return "OpSubgroupAvcSicSetBilinearFilterEnableINTEL"; - case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: return "OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL"; - case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: return "OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL"; - case OpSubgroupAvcSicEvaluateIpeINTEL: return "OpSubgroupAvcSicEvaluateIpeINTEL"; - case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: return "OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL"; - case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: return "OpSubgroupAvcSicEvaluateWithDualReferenceINTEL"; - case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: return "OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL"; - case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: return "OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL"; - case OpSubgroupAvcSicConvertToMceResultINTEL: return "OpSubgroupAvcSicConvertToMceResultINTEL"; - case OpSubgroupAvcSicGetIpeLumaShapeINTEL: return "OpSubgroupAvcSicGetIpeLumaShapeINTEL"; - case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: return "OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL"; - case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: return "OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL"; - case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: return "OpSubgroupAvcSicGetPackedIpeLumaModesINTEL"; - case OpSubgroupAvcSicGetIpeChromaModeINTEL: return "OpSubgroupAvcSicGetIpeChromaModeINTEL"; - case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: return "OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL"; - case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: return "OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL"; - case OpSubgroupAvcSicGetInterRawSadsINTEL: return "OpSubgroupAvcSicGetInterRawSadsINTEL"; - case OpVariableLengthArrayINTEL: return "OpVariableLengthArrayINTEL"; - case OpSaveMemoryINTEL: return "OpSaveMemoryINTEL"; - case OpRestoreMemoryINTEL: return "OpRestoreMemoryINTEL"; - case OpArbitraryFloatSinCosPiINTEL: return "OpArbitraryFloatSinCosPiINTEL"; - case OpArbitraryFloatCastINTEL: return "OpArbitraryFloatCastINTEL"; - case OpArbitraryFloatCastFromIntINTEL: return "OpArbitraryFloatCastFromIntINTEL"; - case OpArbitraryFloatCastToIntINTEL: return "OpArbitraryFloatCastToIntINTEL"; - case OpArbitraryFloatAddINTEL: return "OpArbitraryFloatAddINTEL"; - case OpArbitraryFloatSubINTEL: return "OpArbitraryFloatSubINTEL"; - case OpArbitraryFloatMulINTEL: return "OpArbitraryFloatMulINTEL"; - case OpArbitraryFloatDivINTEL: return "OpArbitraryFloatDivINTEL"; - case OpArbitraryFloatGTINTEL: return "OpArbitraryFloatGTINTEL"; - case OpArbitraryFloatGEINTEL: return "OpArbitraryFloatGEINTEL"; - case OpArbitraryFloatLTINTEL: return "OpArbitraryFloatLTINTEL"; - case OpArbitraryFloatLEINTEL: return "OpArbitraryFloatLEINTEL"; - case OpArbitraryFloatEQINTEL: return "OpArbitraryFloatEQINTEL"; - case OpArbitraryFloatRecipINTEL: return "OpArbitraryFloatRecipINTEL"; - case OpArbitraryFloatRSqrtINTEL: return "OpArbitraryFloatRSqrtINTEL"; - case OpArbitraryFloatCbrtINTEL: return "OpArbitraryFloatCbrtINTEL"; - case OpArbitraryFloatHypotINTEL: return "OpArbitraryFloatHypotINTEL"; - case OpArbitraryFloatSqrtINTEL: return "OpArbitraryFloatSqrtINTEL"; - case OpArbitraryFloatLogINTEL: return "OpArbitraryFloatLogINTEL"; - case OpArbitraryFloatLog2INTEL: return "OpArbitraryFloatLog2INTEL"; - case OpArbitraryFloatLog10INTEL: return "OpArbitraryFloatLog10INTEL"; - case OpArbitraryFloatLog1pINTEL: return "OpArbitraryFloatLog1pINTEL"; - case OpArbitraryFloatExpINTEL: return "OpArbitraryFloatExpINTEL"; - case OpArbitraryFloatExp2INTEL: return "OpArbitraryFloatExp2INTEL"; - case OpArbitraryFloatExp10INTEL: return "OpArbitraryFloatExp10INTEL"; - case OpArbitraryFloatExpm1INTEL: return "OpArbitraryFloatExpm1INTEL"; - case OpArbitraryFloatSinINTEL: return "OpArbitraryFloatSinINTEL"; - case OpArbitraryFloatCosINTEL: return "OpArbitraryFloatCosINTEL"; - case OpArbitraryFloatSinCosINTEL: return "OpArbitraryFloatSinCosINTEL"; - case OpArbitraryFloatSinPiINTEL: return "OpArbitraryFloatSinPiINTEL"; - case OpArbitraryFloatCosPiINTEL: return "OpArbitraryFloatCosPiINTEL"; - case OpArbitraryFloatASinINTEL: return "OpArbitraryFloatASinINTEL"; - case OpArbitraryFloatASinPiINTEL: return "OpArbitraryFloatASinPiINTEL"; - case OpArbitraryFloatACosINTEL: return "OpArbitraryFloatACosINTEL"; - case OpArbitraryFloatACosPiINTEL: return "OpArbitraryFloatACosPiINTEL"; - case OpArbitraryFloatATanINTEL: return "OpArbitraryFloatATanINTEL"; - case OpArbitraryFloatATanPiINTEL: return "OpArbitraryFloatATanPiINTEL"; - case OpArbitraryFloatATan2INTEL: return "OpArbitraryFloatATan2INTEL"; - case OpArbitraryFloatPowINTEL: return "OpArbitraryFloatPowINTEL"; - case OpArbitraryFloatPowRINTEL: return "OpArbitraryFloatPowRINTEL"; - case OpArbitraryFloatPowNINTEL: return "OpArbitraryFloatPowNINTEL"; - case OpLoopControlINTEL: return "OpLoopControlINTEL"; - case OpAliasDomainDeclINTEL: return "OpAliasDomainDeclINTEL"; - case OpAliasScopeDeclINTEL: return "OpAliasScopeDeclINTEL"; - case OpAliasScopeListDeclINTEL: return "OpAliasScopeListDeclINTEL"; - case OpFixedSqrtINTEL: return "OpFixedSqrtINTEL"; - case OpFixedRecipINTEL: return "OpFixedRecipINTEL"; - case OpFixedRsqrtINTEL: return "OpFixedRsqrtINTEL"; - case OpFixedSinINTEL: return "OpFixedSinINTEL"; - case OpFixedCosINTEL: return "OpFixedCosINTEL"; - case OpFixedSinCosINTEL: return "OpFixedSinCosINTEL"; - case OpFixedSinPiINTEL: return "OpFixedSinPiINTEL"; - case OpFixedCosPiINTEL: return "OpFixedCosPiINTEL"; - case OpFixedSinCosPiINTEL: return "OpFixedSinCosPiINTEL"; - case OpFixedLogINTEL: return "OpFixedLogINTEL"; - case OpFixedExpINTEL: return "OpFixedExpINTEL"; - case OpPtrCastToCrossWorkgroupINTEL: return "OpPtrCastToCrossWorkgroupINTEL"; - case OpCrossWorkgroupCastToPtrINTEL: return "OpCrossWorkgroupCastToPtrINTEL"; - case OpReadPipeBlockingINTEL: return "OpReadPipeBlockingINTEL"; - case OpWritePipeBlockingINTEL: return "OpWritePipeBlockingINTEL"; - case OpFPGARegINTEL: return "OpFPGARegINTEL"; - case OpRayQueryGetRayTMinKHR: return "OpRayQueryGetRayTMinKHR"; - case OpRayQueryGetRayFlagsKHR: return "OpRayQueryGetRayFlagsKHR"; - case OpRayQueryGetIntersectionTKHR: return "OpRayQueryGetIntersectionTKHR"; - case OpRayQueryGetIntersectionInstanceCustomIndexKHR: return "OpRayQueryGetIntersectionInstanceCustomIndexKHR"; - case OpRayQueryGetIntersectionInstanceIdKHR: return "OpRayQueryGetIntersectionInstanceIdKHR"; - case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR"; - case OpRayQueryGetIntersectionGeometryIndexKHR: return "OpRayQueryGetIntersectionGeometryIndexKHR"; - case OpRayQueryGetIntersectionPrimitiveIndexKHR: return "OpRayQueryGetIntersectionPrimitiveIndexKHR"; - case OpRayQueryGetIntersectionBarycentricsKHR: return "OpRayQueryGetIntersectionBarycentricsKHR"; - case OpRayQueryGetIntersectionFrontFaceKHR: return "OpRayQueryGetIntersectionFrontFaceKHR"; - case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR"; - case OpRayQueryGetIntersectionObjectRayDirectionKHR: return "OpRayQueryGetIntersectionObjectRayDirectionKHR"; - case OpRayQueryGetIntersectionObjectRayOriginKHR: return "OpRayQueryGetIntersectionObjectRayOriginKHR"; - case OpRayQueryGetWorldRayDirectionKHR: return "OpRayQueryGetWorldRayDirectionKHR"; - case OpRayQueryGetWorldRayOriginKHR: return "OpRayQueryGetWorldRayOriginKHR"; - case OpRayQueryGetIntersectionObjectToWorldKHR: return "OpRayQueryGetIntersectionObjectToWorldKHR"; - case OpRayQueryGetIntersectionWorldToObjectKHR: return "OpRayQueryGetIntersectionWorldToObjectKHR"; - case OpAtomicFAddEXT: return "OpAtomicFAddEXT"; - case OpTypeBufferSurfaceINTEL: return "OpTypeBufferSurfaceINTEL"; - case OpTypeStructContinuedINTEL: return "OpTypeStructContinuedINTEL"; - case OpConstantCompositeContinuedINTEL: return "OpConstantCompositeContinuedINTEL"; - case OpSpecConstantCompositeContinuedINTEL: return "OpSpecConstantCompositeContinuedINTEL"; - case OpCompositeConstructContinuedINTEL: return "OpCompositeConstructContinuedINTEL"; - case OpConvertFToBF16INTEL: return "OpConvertFToBF16INTEL"; - case OpConvertBF16ToFINTEL: return "OpConvertBF16ToFINTEL"; - case OpControlBarrierArriveINTEL: return "OpControlBarrierArriveINTEL"; - case OpControlBarrierWaitINTEL: return "OpControlBarrierWaitINTEL"; - case OpArithmeticFenceEXT: return "OpArithmeticFenceEXT"; - case OpSubgroupBlockPrefetchINTEL: return "OpSubgroupBlockPrefetchINTEL"; - case OpGroupIMulKHR: return "OpGroupIMulKHR"; - case OpGroupFMulKHR: return "OpGroupFMulKHR"; - case OpGroupBitwiseAndKHR: return "OpGroupBitwiseAndKHR"; - case OpGroupBitwiseOrKHR: return "OpGroupBitwiseOrKHR"; - case OpGroupBitwiseXorKHR: return "OpGroupBitwiseXorKHR"; - case OpGroupLogicalAndKHR: return "OpGroupLogicalAndKHR"; - case OpGroupLogicalOrKHR: return "OpGroupLogicalOrKHR"; - case OpGroupLogicalXorKHR: return "OpGroupLogicalXorKHR"; - case OpMaskedGatherINTEL: return "OpMaskedGatherINTEL"; - case OpMaskedScatterINTEL: return "OpMaskedScatterINTEL"; - default: return "Unknown"; - } -} - -#endif /* SPV_ENABLE_UTILITY_CODE */ - -// Overload bitwise operators for mask bit combining - -inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } -inline ImageOperandsMask operator&(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) & unsigned(b)); } -inline ImageOperandsMask operator^(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) ^ unsigned(b)); } -inline ImageOperandsMask operator~(ImageOperandsMask a) { return ImageOperandsMask(~unsigned(a)); } -inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } -inline FPFastMathModeMask operator&(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) & unsigned(b)); } -inline FPFastMathModeMask operator^(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) ^ unsigned(b)); } -inline FPFastMathModeMask operator~(FPFastMathModeMask a) { return FPFastMathModeMask(~unsigned(a)); } -inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } -inline SelectionControlMask operator&(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) & unsigned(b)); } -inline SelectionControlMask operator^(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) ^ unsigned(b)); } -inline SelectionControlMask operator~(SelectionControlMask a) { return SelectionControlMask(~unsigned(a)); } -inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } -inline LoopControlMask operator&(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) & unsigned(b)); } -inline LoopControlMask operator^(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) ^ unsigned(b)); } -inline LoopControlMask operator~(LoopControlMask a) { return LoopControlMask(~unsigned(a)); } -inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } -inline FunctionControlMask operator&(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) & unsigned(b)); } -inline FunctionControlMask operator^(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) ^ unsigned(b)); } -inline FunctionControlMask operator~(FunctionControlMask a) { return FunctionControlMask(~unsigned(a)); } -inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } -inline MemorySemanticsMask operator&(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) & unsigned(b)); } -inline MemorySemanticsMask operator^(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) ^ unsigned(b)); } -inline MemorySemanticsMask operator~(MemorySemanticsMask a) { return MemorySemanticsMask(~unsigned(a)); } -inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } -inline MemoryAccessMask operator&(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) & unsigned(b)); } -inline MemoryAccessMask operator^(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) ^ unsigned(b)); } -inline MemoryAccessMask operator~(MemoryAccessMask a) { return MemoryAccessMask(~unsigned(a)); } -inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } -inline KernelProfilingInfoMask operator&(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) & unsigned(b)); } -inline KernelProfilingInfoMask operator^(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) ^ unsigned(b)); } -inline KernelProfilingInfoMask operator~(KernelProfilingInfoMask a) { return KernelProfilingInfoMask(~unsigned(a)); } -inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } -inline RayFlagsMask operator&(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) & unsigned(b)); } -inline RayFlagsMask operator^(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) ^ unsigned(b)); } -inline RayFlagsMask operator~(RayFlagsMask a) { return RayFlagsMask(~unsigned(a)); } -inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) | unsigned(b)); } -inline FragmentShadingRateMask operator&(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) & unsigned(b)); } -inline FragmentShadingRateMask operator^(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) ^ unsigned(b)); } -inline FragmentShadingRateMask operator~(FragmentShadingRateMask a) { return FragmentShadingRateMask(~unsigned(a)); } -inline CooperativeMatrixOperandsMask operator|(CooperativeMatrixOperandsMask a, CooperativeMatrixOperandsMask b) { return CooperativeMatrixOperandsMask(unsigned(a) | unsigned(b)); } -inline CooperativeMatrixOperandsMask operator&(CooperativeMatrixOperandsMask a, CooperativeMatrixOperandsMask b) { return CooperativeMatrixOperandsMask(unsigned(a) & unsigned(b)); } -inline CooperativeMatrixOperandsMask operator^(CooperativeMatrixOperandsMask a, CooperativeMatrixOperandsMask b) { return CooperativeMatrixOperandsMask(unsigned(a) ^ unsigned(b)); } -inline CooperativeMatrixOperandsMask operator~(CooperativeMatrixOperandsMask a) { return CooperativeMatrixOperandsMask(~unsigned(a)); } -inline CooperativeMatrixReduceMask operator|(CooperativeMatrixReduceMask a, CooperativeMatrixReduceMask b) { return CooperativeMatrixReduceMask(unsigned(a) | unsigned(b)); } -inline CooperativeMatrixReduceMask operator&(CooperativeMatrixReduceMask a, CooperativeMatrixReduceMask b) { return CooperativeMatrixReduceMask(unsigned(a) & unsigned(b)); } -inline CooperativeMatrixReduceMask operator^(CooperativeMatrixReduceMask a, CooperativeMatrixReduceMask b) { return CooperativeMatrixReduceMask(unsigned(a) ^ unsigned(b)); } -inline CooperativeMatrixReduceMask operator~(CooperativeMatrixReduceMask a) { return CooperativeMatrixReduceMask(~unsigned(a)); } -inline TensorAddressingOperandsMask operator|(TensorAddressingOperandsMask a, TensorAddressingOperandsMask b) { return TensorAddressingOperandsMask(unsigned(a) | unsigned(b)); } -inline TensorAddressingOperandsMask operator&(TensorAddressingOperandsMask a, TensorAddressingOperandsMask b) { return TensorAddressingOperandsMask(unsigned(a) & unsigned(b)); } -inline TensorAddressingOperandsMask operator^(TensorAddressingOperandsMask a, TensorAddressingOperandsMask b) { return TensorAddressingOperandsMask(unsigned(a) ^ unsigned(b)); } -inline TensorAddressingOperandsMask operator~(TensorAddressingOperandsMask a) { return TensorAddressingOperandsMask(~unsigned(a)); } -inline RawAccessChainOperandsMask operator|(RawAccessChainOperandsMask a, RawAccessChainOperandsMask b) { return RawAccessChainOperandsMask(unsigned(a) | unsigned(b)); } -inline RawAccessChainOperandsMask operator&(RawAccessChainOperandsMask a, RawAccessChainOperandsMask b) { return RawAccessChainOperandsMask(unsigned(a) & unsigned(b)); } -inline RawAccessChainOperandsMask operator^(RawAccessChainOperandsMask a, RawAccessChainOperandsMask b) { return RawAccessChainOperandsMask(unsigned(a) ^ unsigned(b)); } -inline RawAccessChainOperandsMask operator~(RawAccessChainOperandsMask a) { return RawAccessChainOperandsMask(~unsigned(a)); } - -} // end namespace spv - -#endif // #ifndef spirv_HPP - diff --git a/include/SPIRV/spvIR.h b/include/SPIRV/spvIR.h deleted file mode 100644 index e723f0e1..00000000 --- a/include/SPIRV/spvIR.h +++ /dev/null @@ -1,592 +0,0 @@ -// -// Copyright (C) 2014 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// SPIRV-IR -// -// Simple in-memory representation (IR) of SPIRV. Just for holding -// Each function's CFG of blocks. Has this hierarchy: -// - Module, which is a list of -// - Function, which is a list of -// - Block, which is a list of -// - Instruction -// - -#pragma once -#ifndef spvIR_H -#define spvIR_H - -#include "spirv.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace spv { - -class Block; -class Function; -class Module; - -const Id NoResult = 0; -const Id NoType = 0; - -const Decoration NoPrecision = DecorationMax; - -#ifdef __GNUC__ -# define POTENTIALLY_UNUSED __attribute__((unused)) -#else -# define POTENTIALLY_UNUSED -#endif - -POTENTIALLY_UNUSED -const MemorySemanticsMask MemorySemanticsAllMemory = - (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | - MemorySemanticsWorkgroupMemoryMask | - MemorySemanticsAtomicCounterMemoryMask | - MemorySemanticsImageMemoryMask); - -struct IdImmediate { - bool isId; // true if word is an Id, false if word is an immediate - unsigned word; - IdImmediate(bool i, unsigned w) : isId(i), word(w) {} -}; - -// -// SPIR-V IR instruction. -// - -class Instruction { -public: - Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } - explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } - virtual ~Instruction() {} - void reserveOperands(size_t count) { - operands.reserve(count); - idOperand.reserve(count); - } - void addIdOperand(Id id) { - // ids can't be 0 - assert(id); - operands.push_back(id); - idOperand.push_back(true); - } - // This method is potentially dangerous as it can break assumptions - // about SSA and lack of forward references. - void setIdOperand(unsigned idx, Id id) { - assert(id); - assert(idOperand[idx]); - operands[idx] = id; - } - - void addImmediateOperand(unsigned int immediate) { - operands.push_back(immediate); - idOperand.push_back(false); - } - void setImmediateOperand(unsigned idx, unsigned int immediate) { - assert(!idOperand[idx]); - operands[idx] = immediate; - } - - void addStringOperand(const char* str) - { - unsigned int word = 0; - unsigned int shiftAmount = 0; - char c; - - do { - c = *(str++); - word |= ((unsigned int)c) << shiftAmount; - shiftAmount += 8; - if (shiftAmount == 32) { - addImmediateOperand(word); - word = 0; - shiftAmount = 0; - } - } while (c != 0); - - // deal with partial last word - if (shiftAmount > 0) { - addImmediateOperand(word); - } - } - bool isIdOperand(int op) const { return idOperand[op]; } - void setBlock(Block* b) { block = b; } - Block* getBlock() const { return block; } - Op getOpCode() const { return opCode; } - int getNumOperands() const - { - assert(operands.size() == idOperand.size()); - return (int)operands.size(); - } - Id getResultId() const { return resultId; } - Id getTypeId() const { return typeId; } - Id getIdOperand(int op) const { - assert(idOperand[op]); - return operands[op]; - } - unsigned int getImmediateOperand(int op) const { - assert(!idOperand[op]); - return operands[op]; - } - - // Write out the binary form. - void dump(std::vector& out) const - { - // Compute the wordCount - unsigned int wordCount = 1; - if (typeId) - ++wordCount; - if (resultId) - ++wordCount; - wordCount += (unsigned int)operands.size(); - - // Write out the beginning of the instruction - out.push_back(((wordCount) << WordCountShift) | opCode); - if (typeId) - out.push_back(typeId); - if (resultId) - out.push_back(resultId); - - // Write out the operands - for (int op = 0; op < (int)operands.size(); ++op) - out.push_back(operands[op]); - } - - const char *getNameString() const { - if (opCode == OpString) { - return (const char *)&operands[0]; - } else { - assert(opCode == OpName); - return (const char *)&operands[1]; - } - } - -protected: - Instruction(const Instruction&); - Id resultId; - Id typeId; - Op opCode; - std::vector operands; // operands, both and immediates (both are unsigned int) - std::vector idOperand; // true for operands that are , false for immediates - Block* block; -}; - -// -// SPIR-V IR block. -// - -struct DebugSourceLocation { - int line; - int column; - spv::Id fileId; -}; - -class Block { -public: - Block(Id id, Function& parent); - virtual ~Block() - { - } - - Id getId() { return instructions.front()->getResultId(); } - - Function& getParent() const { return parent; } - // Returns true if the source location is actually updated. - // Note we still need the builder to insert the line marker instruction. This is just a tracker. - bool updateDebugSourceLocation(int line, int column, spv::Id fileId) { - if (currentSourceLoc && currentSourceLoc->line == line && currentSourceLoc->column == column && - currentSourceLoc->fileId == fileId) { - return false; - } - - currentSourceLoc = DebugSourceLocation{line, column, fileId}; - return true; - } - // Returns true if the scope is actually updated. - // Note we still need the builder to insert the debug scope instruction. This is just a tracker. - bool updateDebugScope(spv::Id scopeId) { - assert(scopeId); - if (currentDebugScope && *currentDebugScope == scopeId) { - return false; - } - - currentDebugScope = scopeId; - return true; - } - void addInstruction(std::unique_ptr inst); - void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} - void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } - const std::vector& getPredecessors() const { return predecessors; } - const std::vector& getSuccessors() const { return successors; } - std::vector >& getInstructions() { - return instructions; - } - const std::vector >& getLocalVariables() const { return localVariables; } - void setUnreachable() { unreachable = true; } - bool isUnreachable() const { return unreachable; } - // Returns the block's merge instruction, if one exists (otherwise null). - const Instruction* getMergeInstruction() const { - if (instructions.size() < 2) return nullptr; - const Instruction* nextToLast = (instructions.cend() - 2)->get(); - switch (nextToLast->getOpCode()) { - case OpSelectionMerge: - case OpLoopMerge: - return nextToLast; - default: - return nullptr; - } - return nullptr; - } - - // Change this block into a canonical dead merge block. Delete instructions - // as necessary. A canonical dead merge block has only an OpLabel and an - // OpUnreachable. - void rewriteAsCanonicalUnreachableMerge() { - assert(localVariables.empty()); - // Delete all instructions except for the label. - assert(instructions.size() > 0); - instructions.resize(1); - successors.clear(); - addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); - } - // Change this block into a canonical dead continue target branching to the - // given header ID. Delete instructions as necessary. A canonical dead continue - // target has only an OpLabel and an unconditional branch back to the corresponding - // header. - void rewriteAsCanonicalUnreachableContinue(Block* header) { - assert(localVariables.empty()); - // Delete all instructions except for the label. - assert(instructions.size() > 0); - instructions.resize(1); - successors.clear(); - // Add OpBranch back to the header. - assert(header != nullptr); - Instruction* branch = new Instruction(OpBranch); - branch->addIdOperand(header->getId()); - addInstruction(std::unique_ptr(branch)); - successors.push_back(header); - } - - bool isTerminated() const - { - switch (instructions.back()->getOpCode()) { - case OpBranch: - case OpBranchConditional: - case OpSwitch: - case OpKill: - case OpTerminateInvocation: - case OpReturn: - case OpReturnValue: - case OpUnreachable: - return true; - default: - return false; - } - } - - void dump(std::vector& out) const - { - instructions[0]->dump(out); - for (int i = 0; i < (int)localVariables.size(); ++i) - localVariables[i]->dump(out); - for (int i = 1; i < (int)instructions.size(); ++i) - instructions[i]->dump(out); - } - -protected: - Block(const Block&); - Block& operator=(Block&); - - // To enforce keeping parent and ownership in sync: - friend Function; - - std::vector > instructions; - std::vector predecessors, successors; - std::vector > localVariables; - Function& parent; - - // Track source location of the last source location marker instruction. - std::optional currentSourceLoc; - - // Track scope of the last debug scope instruction. - std::optional currentDebugScope; - - // track whether this block is known to be uncreachable (not necessarily - // true for all unreachable blocks, but should be set at least - // for the extraneous ones introduced by the builder). - bool unreachable; -}; - -// The different reasons for reaching a block in the inReadableOrder traversal. -enum ReachReason { - // Reachable from the entry block via transfers of control, i.e. branches. - ReachViaControlFlow = 0, - // A continue target that is not reachable via control flow. - ReachDeadContinue, - // A merge block that is not reachable via control flow. - ReachDeadMerge -}; - -// Traverses the control-flow graph rooted at root in an order suited for -// readable code generation. Invokes callback at every node in the traversal -// order. The callback arguments are: -// - the block, -// - the reason we reached the block, -// - if the reason was that block is an unreachable continue or unreachable merge block -// then the last parameter is the corresponding header block. -void inReadableOrder(Block* root, std::function callback); - -// -// SPIR-V IR Function. -// - -class Function { -public: - Function(Id id, Id resultType, Id functionType, Id firstParam, LinkageType linkage, const std::string& name, Module& parent); - virtual ~Function() - { - for (int i = 0; i < (int)parameterInstructions.size(); ++i) - delete parameterInstructions[i]; - - for (int i = 0; i < (int)blocks.size(); ++i) - delete blocks[i]; - } - Id getId() const { return functionInstruction.getResultId(); } - Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } - Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } - - void addBlock(Block* block) { blocks.push_back(block); } - void removeBlock(Block* block) - { - auto found = find(blocks.begin(), blocks.end(), block); - assert(found != blocks.end()); - blocks.erase(found); - delete block; - } - - Module& getParent() const { return parent; } - Block* getEntryBlock() const { return blocks.front(); } - Block* getLastBlock() const { return blocks.back(); } - const std::vector& getBlocks() const { return blocks; } - void addLocalVariable(std::unique_ptr inst); - Id getReturnType() const { return functionInstruction.getTypeId(); } - Id getFuncId() const { return functionInstruction.getResultId(); } - Id getFuncTypeId() const { return functionInstruction.getIdOperand(1); } - void setReturnPrecision(Decoration precision) - { - if (precision == DecorationRelaxedPrecision) - reducedPrecisionReturn = true; - } - Decoration getReturnPrecision() const - { return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; } - - void setDebugLineInfo(Id fileName, int line, int column) { - lineInstruction = std::unique_ptr{new Instruction(OpLine)}; - lineInstruction->reserveOperands(3); - lineInstruction->addIdOperand(fileName); - lineInstruction->addImmediateOperand(line); - lineInstruction->addImmediateOperand(column); - } - bool hasDebugLineInfo() const { return lineInstruction != nullptr; } - - void setImplicitThis() { implicitThis = true; } - bool hasImplicitThis() const { return implicitThis; } - - void addParamPrecision(unsigned param, Decoration precision) - { - if (precision == DecorationRelaxedPrecision) - reducedPrecisionParams.insert(param); - } - Decoration getParamPrecision(unsigned param) const - { - return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ? - DecorationRelaxedPrecision : NoPrecision; - } - - void dump(std::vector& out) const - { - // OpLine - if (lineInstruction != nullptr) { - lineInstruction->dump(out); - } - - // OpFunction - functionInstruction.dump(out); - - // OpFunctionParameter - for (int p = 0; p < (int)parameterInstructions.size(); ++p) - parameterInstructions[p]->dump(out); - - // Blocks - inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); - Instruction end(0, 0, OpFunctionEnd); - end.dump(out); - } - - LinkageType getLinkType() const { return linkType; } - const char* getExportName() const { return exportName.c_str(); } - -protected: - Function(const Function&); - Function& operator=(Function&); - - Module& parent; - std::unique_ptr lineInstruction; - Instruction functionInstruction; - std::vector parameterInstructions; - std::vector blocks; - bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument - bool reducedPrecisionReturn; - std::set reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg - LinkageType linkType; - std::string exportName; -}; - -// -// SPIR-V IR Module. -// - -class Module { -public: - Module() {} - virtual ~Module() - { - // TODO delete things - } - - void addFunction(Function *fun) { functions.push_back(fun); } - - void mapInstruction(Instruction *instruction) - { - spv::Id resultId = instruction->getResultId(); - // map the instruction's result id - if (resultId >= idToInstruction.size()) - idToInstruction.resize(resultId + 16); - idToInstruction[resultId] = instruction; - } - - Instruction* getInstruction(Id id) const { return idToInstruction[id]; } - const std::vector& getFunctions() const { return functions; } - spv::Id getTypeId(Id resultId) const { - return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); - } - StorageClass getStorageClass(Id typeId) const - { - assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); - return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); - } - - void dump(std::vector& out) const - { - for (int f = 0; f < (int)functions.size(); ++f) - functions[f]->dump(out); - } - -protected: - Module(const Module&); - std::vector functions; - - // map from result id to instruction having that result id - std::vector idToInstruction; - - // map from a result id to its type id -}; - -// -// Implementation (it's here due to circular type definitions). -// - -// Add both -// - the OpFunction instruction -// - all the OpFunctionParameter instructions -__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, LinkageType linkage, const std::string& name, Module& parent) - : parent(parent), lineInstruction(nullptr), - functionInstruction(id, resultType, OpFunction), implicitThis(false), - reducedPrecisionReturn(false), - linkType(linkage) -{ - // OpFunction - functionInstruction.reserveOperands(2); - functionInstruction.addImmediateOperand(FunctionControlMaskNone); - functionInstruction.addIdOperand(functionType); - parent.mapInstruction(&functionInstruction); - parent.addFunction(this); - - // OpFunctionParameter - Instruction* typeInst = parent.getInstruction(functionType); - int numParams = typeInst->getNumOperands() - 1; - for (int p = 0; p < numParams; ++p) { - Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); - parent.mapInstruction(param); - parameterInstructions.push_back(param); - } - - // If importing/exporting, save the function name (without the mangled parameters) for the linkage decoration - if (linkType != LinkageTypeMax) { - exportName = name.substr(0, name.find_first_of('(')); - } -} - -__inline void Function::addLocalVariable(std::unique_ptr inst) -{ - Instruction* raw_instruction = inst.get(); - blocks[0]->addLocalVariable(std::move(inst)); - parent.mapInstruction(raw_instruction); -} - -__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) -{ - instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); - instructions.back()->setBlock(this); - parent.getParent().mapInstruction(instructions.back().get()); -} - -__inline void Block::addInstruction(std::unique_ptr inst) -{ - Instruction* raw_instruction = inst.get(); - instructions.push_back(std::move(inst)); - raw_instruction->setBlock(this); - if (raw_instruction->getResultId()) - parent.getParent().mapInstruction(raw_instruction); -} - -} // end spv namespace - -#endif // spvIR_H