From 0e0da8893be60cb20bb6c3b8badddd142f0c1072 Mon Sep 17 00:00:00 2001 From: coulsonwang Date: Wed, 6 May 2020 14:51:31 +0800 Subject: [PATCH] add glslang and spirv-cross for ios --- android/CMakeLists.txt | 8 +- ios/CMakeLists.txt | 38 + ios/include/SPIRV/GLSL.ext.AMD.h | 108 + ios/include/SPIRV/GLSL.ext.EXT.h | 39 + ios/include/SPIRV/GLSL.ext.KHR.h | 51 + ios/include/SPIRV/GLSL.ext.NV.h | 81 + ios/include/SPIRV/GLSL.std.450.h | 131 + ios/include/SPIRV/GlslangToSpv.h | 61 + ios/include/SPIRV/Logger.h | 83 + ios/include/SPIRV/NonSemanticDebugPrintf.h | 50 + ios/include/SPIRV/SPVRemapper.h | 304 ++ ios/include/SPIRV/SpvBuilder.h | 838 ++++++ ios/include/SPIRV/SpvTools.h | 82 + ios/include/SPIRV/bitutils.h | 81 + ios/include/SPIRV/disassemble.h | 53 + ios/include/SPIRV/doc.h | 258 ++ ios/include/SPIRV/hex_float.h | 1078 +++++++ ios/include/SPIRV/spirv.hpp | 2114 ++++++++++++++ ios/include/SPIRV/spvIR.h | 485 ++++ ios/include/glslang/Include/BaseTypes.h | 565 ++++ ios/include/glslang/Include/Common.h | 292 ++ ios/include/glslang/Include/ConstantUnion.h | 974 +++++++ ios/include/glslang/Include/InfoSink.h | 144 + .../glslang/Include/InitializeGlobals.h | 44 + ios/include/glslang/Include/PoolAlloc.h | 316 +++ ios/include/glslang/Include/ResourceLimits.h | 149 + ios/include/glslang/Include/ShHandle.h | 176 ++ ios/include/glslang/Include/Types.h | 2483 +++++++++++++++++ ios/include/glslang/Include/arrays.h | 341 +++ .../glslang/Include/glslang_c_interface.h | 232 ++ .../glslang/Include/glslang_c_shader_types.h | 182 ++ ios/include/glslang/Include/intermediate.h | 1805 ++++++++++++ ios/include/glslang/Include/revision.h | 3 + .../glslang/MachineIndependent/Initialize.h | 112 + .../MachineIndependent/LiveTraverser.h | 138 + .../glslang/MachineIndependent/ParseHelper.h | 525 ++++ .../glslang/MachineIndependent/RemoveTree.h | 41 + ios/include/glslang/MachineIndependent/Scan.h | 276 ++ .../glslang/MachineIndependent/ScanContext.h | 93 + .../glslang/MachineIndependent/SymbolTable.h | 885 ++++++ .../glslang/MachineIndependent/Versions.h | 327 +++ .../glslang/MachineIndependent/attribute.h | 149 + .../glslang/MachineIndependent/gl_types.h | 210 ++ .../MachineIndependent/glslang_tab.cpp.h | 521 ++++ .../glslang/MachineIndependent/iomapper.h | 300 ++ .../MachineIndependent/localintermediate.h | 1013 +++++++ .../MachineIndependent/parseVersions.h | 236 ++ .../preprocessor/PpContext.h | 703 +++++ .../preprocessor/PpTokens.h | 179 ++ .../propagateNoContraction.h | 55 + .../glslang/MachineIndependent/reflection.h | 223 ++ ios/include/glslang/Public/ShaderLang.h | 927 ++++++ ios/include/glslang/SPIRV/GLSL.ext.AMD.h | 108 + ios/include/glslang/SPIRV/GLSL.ext.EXT.h | 39 + ios/include/glslang/SPIRV/GLSL.ext.KHR.h | 51 + ios/include/glslang/SPIRV/GLSL.ext.NV.h | 81 + ios/include/glslang/SPIRV/GLSL.std.450.h | 131 + ios/include/glslang/SPIRV/GlslangToSpv.h | 61 + ios/include/glslang/SPIRV/Logger.h | 83 + .../glslang/SPIRV/NonSemanticDebugPrintf.h | 50 + ios/include/glslang/SPIRV/SPVRemapper.h | 304 ++ ios/include/glslang/SPIRV/SpvBuilder.h | 838 ++++++ ios/include/glslang/SPIRV/SpvTools.h | 82 + ios/include/glslang/SPIRV/bitutils.h | 81 + ios/include/glslang/SPIRV/disassemble.h | 53 + ios/include/glslang/SPIRV/doc.h | 258 ++ ios/include/glslang/SPIRV/hex_float.h | 1078 +++++++ ios/include/glslang/SPIRV/spirv.hpp | 2114 ++++++++++++++ ios/include/glslang/SPIRV/spvIR.h | 485 ++++ ios/include/spirv_cross/GLSL.std.450.h | 131 + ios/include/spirv_cross/spirv.h | 2104 ++++++++++++++ ios/include/spirv_cross/spirv.hpp | 2114 ++++++++++++++ ios/include/spirv_cross/spirv_cfg.hpp | 156 ++ ios/include/spirv_cross/spirv_common.hpp | 1781 ++++++++++++ ios/include/spirv_cross/spirv_cpp.hpp | 86 + ios/include/spirv_cross/spirv_cross.hpp | 1055 +++++++ ios/include/spirv_cross/spirv_cross_c.h | 912 ++++++ .../spirv_cross/spirv_cross_containers.hpp | 734 +++++ .../spirv_cross_error_handling.hpp | 87 + .../spirv_cross/spirv_cross_parsed_ir.hpp | 231 ++ ios/include/spirv_cross/spirv_cross_util.hpp | 30 + ios/include/spirv_cross/spirv_glsl.hpp | 760 +++++ ios/include/spirv_cross/spirv_hlsl.hpp | 329 +++ ios/include/spirv_cross/spirv_msl.hpp | 962 +++++++ ios/include/spirv_cross/spirv_parser.hpp | 93 + ios/include/spirv_cross/spirv_reflect.hpp | 83 + ios/libs/libOGLCompiler.a | Bin 0 -> 2608 bytes ios/libs/libOSDependent.a | Bin 0 -> 3768 bytes ios/libs/libSPIRV.a | Bin 0 -> 733392 bytes ios/libs/libglslang.a | Bin 0 -> 2607608 bytes ios/libs/libspirv-cross-core.a | Bin 0 -> 567192 bytes ios/libs/libspirv-cross-glsl.a | Bin 0 -> 1183888 bytes ios/libs/libspirv-cross-msl.a | Bin 0 -> 1595408 bytes mac/CMakeLists.txt | 8 +- 94 files changed, 38107 insertions(+), 8 deletions(-) create mode 100644 ios/include/SPIRV/GLSL.ext.AMD.h create mode 100644 ios/include/SPIRV/GLSL.ext.EXT.h create mode 100644 ios/include/SPIRV/GLSL.ext.KHR.h create mode 100644 ios/include/SPIRV/GLSL.ext.NV.h create mode 100644 ios/include/SPIRV/GLSL.std.450.h create mode 100644 ios/include/SPIRV/GlslangToSpv.h create mode 100644 ios/include/SPIRV/Logger.h create mode 100644 ios/include/SPIRV/NonSemanticDebugPrintf.h create mode 100644 ios/include/SPIRV/SPVRemapper.h create mode 100644 ios/include/SPIRV/SpvBuilder.h create mode 100644 ios/include/SPIRV/SpvTools.h create mode 100644 ios/include/SPIRV/bitutils.h create mode 100644 ios/include/SPIRV/disassemble.h create mode 100644 ios/include/SPIRV/doc.h create mode 100644 ios/include/SPIRV/hex_float.h create mode 100644 ios/include/SPIRV/spirv.hpp create mode 100644 ios/include/SPIRV/spvIR.h create mode 100644 ios/include/glslang/Include/BaseTypes.h create mode 100644 ios/include/glslang/Include/Common.h create mode 100644 ios/include/glslang/Include/ConstantUnion.h create mode 100644 ios/include/glslang/Include/InfoSink.h create mode 100644 ios/include/glslang/Include/InitializeGlobals.h create mode 100644 ios/include/glslang/Include/PoolAlloc.h create mode 100644 ios/include/glslang/Include/ResourceLimits.h create mode 100644 ios/include/glslang/Include/ShHandle.h create mode 100644 ios/include/glslang/Include/Types.h create mode 100644 ios/include/glslang/Include/arrays.h create mode 100644 ios/include/glslang/Include/glslang_c_interface.h create mode 100644 ios/include/glslang/Include/glslang_c_shader_types.h create mode 100644 ios/include/glslang/Include/intermediate.h create mode 100644 ios/include/glslang/Include/revision.h create mode 100644 ios/include/glslang/MachineIndependent/Initialize.h create mode 100644 ios/include/glslang/MachineIndependent/LiveTraverser.h create mode 100644 ios/include/glslang/MachineIndependent/ParseHelper.h create mode 100644 ios/include/glslang/MachineIndependent/RemoveTree.h create mode 100644 ios/include/glslang/MachineIndependent/Scan.h create mode 100644 ios/include/glslang/MachineIndependent/ScanContext.h create mode 100644 ios/include/glslang/MachineIndependent/SymbolTable.h create mode 100644 ios/include/glslang/MachineIndependent/Versions.h create mode 100644 ios/include/glslang/MachineIndependent/attribute.h create mode 100644 ios/include/glslang/MachineIndependent/gl_types.h create mode 100644 ios/include/glslang/MachineIndependent/glslang_tab.cpp.h create mode 100644 ios/include/glslang/MachineIndependent/iomapper.h create mode 100644 ios/include/glslang/MachineIndependent/localintermediate.h create mode 100644 ios/include/glslang/MachineIndependent/parseVersions.h create mode 100644 ios/include/glslang/MachineIndependent/preprocessor/PpContext.h create mode 100644 ios/include/glslang/MachineIndependent/preprocessor/PpTokens.h create mode 100644 ios/include/glslang/MachineIndependent/propagateNoContraction.h create mode 100644 ios/include/glslang/MachineIndependent/reflection.h create mode 100644 ios/include/glslang/Public/ShaderLang.h create mode 100644 ios/include/glslang/SPIRV/GLSL.ext.AMD.h create mode 100644 ios/include/glslang/SPIRV/GLSL.ext.EXT.h create mode 100644 ios/include/glslang/SPIRV/GLSL.ext.KHR.h create mode 100644 ios/include/glslang/SPIRV/GLSL.ext.NV.h create mode 100644 ios/include/glslang/SPIRV/GLSL.std.450.h create mode 100644 ios/include/glslang/SPIRV/GlslangToSpv.h create mode 100644 ios/include/glslang/SPIRV/Logger.h create mode 100644 ios/include/glslang/SPIRV/NonSemanticDebugPrintf.h create mode 100644 ios/include/glslang/SPIRV/SPVRemapper.h create mode 100644 ios/include/glslang/SPIRV/SpvBuilder.h create mode 100644 ios/include/glslang/SPIRV/SpvTools.h create mode 100644 ios/include/glslang/SPIRV/bitutils.h create mode 100644 ios/include/glslang/SPIRV/disassemble.h create mode 100644 ios/include/glslang/SPIRV/doc.h create mode 100644 ios/include/glslang/SPIRV/hex_float.h create mode 100644 ios/include/glslang/SPIRV/spirv.hpp create mode 100644 ios/include/glslang/SPIRV/spvIR.h create mode 100644 ios/include/spirv_cross/GLSL.std.450.h create mode 100644 ios/include/spirv_cross/spirv.h create mode 100644 ios/include/spirv_cross/spirv.hpp create mode 100644 ios/include/spirv_cross/spirv_cfg.hpp create mode 100644 ios/include/spirv_cross/spirv_common.hpp create mode 100644 ios/include/spirv_cross/spirv_cpp.hpp create mode 100644 ios/include/spirv_cross/spirv_cross.hpp create mode 100644 ios/include/spirv_cross/spirv_cross_c.h create mode 100644 ios/include/spirv_cross/spirv_cross_containers.hpp create mode 100644 ios/include/spirv_cross/spirv_cross_error_handling.hpp create mode 100644 ios/include/spirv_cross/spirv_cross_parsed_ir.hpp create mode 100644 ios/include/spirv_cross/spirv_cross_util.hpp create mode 100644 ios/include/spirv_cross/spirv_glsl.hpp create mode 100644 ios/include/spirv_cross/spirv_hlsl.hpp create mode 100644 ios/include/spirv_cross/spirv_msl.hpp create mode 100644 ios/include/spirv_cross/spirv_parser.hpp create mode 100644 ios/include/spirv_cross/spirv_reflect.hpp create mode 100644 ios/libs/libOGLCompiler.a create mode 100644 ios/libs/libOSDependent.a create mode 100644 ios/libs/libSPIRV.a create mode 100644 ios/libs/libglslang.a create mode 100644 ios/libs/libspirv-cross-core.a create mode 100644 ios/libs/libspirv-cross-glsl.a create mode 100644 ios/libs/libspirv-cross-msl.a diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index ab4cafc3..98e95a23 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -175,19 +175,19 @@ endif() add_library(glslang STATIC IMPORTED GLOBAL) set_target_properties(glslang PROPERTIES - IMPORTED_LOCATION ${platform_spec_path}/glslang/glslang.lib + IMPORTED_LOCATION ${platform_spec_path}/glslang/libglslang.lib ) add_library(OGLCompiler STATIC IMPORTED GLOBAL) set_target_properties(OGLCompiler PROPERTIES - IMPORTED_LOCATION ${platform_spec_path}/glslang/OGLCompiler.lib + IMPORTED_LOCATION ${platform_spec_path}/glslang/libOGLCompiler.lib ) add_library(OSDependent STATIC IMPORTED GLOBAL) set_target_properties(OSDependent PROPERTIES - IMPORTED_LOCATION ${platform_spec_path}/glslang/OSDependent.lib + IMPORTED_LOCATION ${platform_spec_path}/glslang/libOSDependent.lib ) add_library(SPIRV STATIC IMPORTED GLOBAL) set_target_properties(SPIRV PROPERTIES - IMPORTED_LOCATION ${platform_spec_path}/glslang/SPIRV.lib + IMPORTED_LOCATION ${platform_spec_path}/glslang/libSPIRV.lib ) set(glslang_libs_name glslang OGLCompiler OSDependent SPIRV) diff --git a/ios/CMakeLists.txt b/ios/CMakeLists.txt index 17cf7d95..59a23cd2 100644 --- a/ios/CMakeLists.txt +++ b/ios/CMakeLists.txt @@ -94,6 +94,44 @@ if(USE_TIFF) ) endif() +if(CC_USE_METAL) + add_library(glslang STATIC IMPORTED GLOBAL) + set_target_properties(glslang PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libglslang.lib + ) + add_library(OGLCompiler STATIC IMPORTED GLOBAL) + set_target_properties(OGLCompiler PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libOGLCompiler.lib + ) + add_library(OSDependent STATIC IMPORTED GLOBAL) + set_target_properties(OSDependent PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libOSDependent.lib + ) + add_library(SPIRV STATIC IMPORTED GLOBAL) + set_target_properties(SPIRV PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libSPIRV.lib + ) + set(glslang_libs_name glslang OGLCompiler OSDependent SPIRV) + + add_library(spirv-cross-core STATIC IMPORTED GLOBAL) + set_target_properties(spirv-cross-core PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libspirv-cross-core.lib + ) + add_library(spirv-cross-msl STATIC IMPORTED GLOBAL) + set_target_properties(spirv-cross-msl PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libspirv-cross-msl.lib + ) + add_library(spirv-cross-glsl STATIC IMPORTED GLOBAL) + set_target_properties(spirv-cross-glsl PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/libs/libspirv-cross-glsl.lib + ) + set(spirv-cross_libs_name spirv-cross-core spirv-cross-glsl spirv-cross-msl) + list(APPEND CC_EXTERNAL_LIBS + ${glslang_libs_name} + ${spirv-cross_libs_name} + ) +endif() + list(APPEND CC_EXTERNAL_INCLUDES ${CMAKE_CURRENT_LIST_DIR}/include ) diff --git a/ios/include/SPIRV/GLSL.ext.AMD.h b/ios/include/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/ios/include/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** 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/ios/include/SPIRV/GLSL.ext.EXT.h b/ios/include/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/ios/include/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** 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"; + +#endif // #ifndef GLSLextEXT_H diff --git a/ios/include/SPIRV/GLSL.ext.KHR.h b/ios/include/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/ios/include/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** 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 = 2; + +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"; +#endif // #ifndef GLSLextKHR_H diff --git a/ios/include/SPIRV/GLSL.ext.NV.h b/ios/include/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/ios/include/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** 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_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"; + +#endif // #ifndef GLSLextNV_H diff --git a/ios/include/SPIRV/GLSL.std.450.h b/ios/include/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/ios/include/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** 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/ios/include/SPIRV/GlslangToSpv.h b/ios/include/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/ios/include/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// 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 + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/ios/include/SPIRV/Logger.h b/ios/include/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/ios/include/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// 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 + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // 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; +#endif + +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/ios/include/SPIRV/NonSemanticDebugPrintf.h b/ios/include/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/ios/include/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// 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/ios/include/SPIRV/SPVRemapper.h b/ios/include/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/ios/include/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// 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 + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +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 + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class 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, 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; + + 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 + + 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 // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/ios/include/SPIRV/SpvBuilder.h b/ios/include/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/ios/include/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// 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" +#include "spirv.hpp" +#include "spvIR.h" + +#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) + { + source = 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; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + 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 setEmitOpLines() { emitOpLines = true; } + 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; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // 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*); + 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 makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // 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; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + 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); } + + 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 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; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + 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)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + 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 makeBoolConstant(bool b, bool specConstant = false); + 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); + + // 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 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 addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // 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, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // 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); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // 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::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 OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(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); + + // 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(); + + // 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(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + 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; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 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; + return *this; + } +#endif + }; + 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, 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 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(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // 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); +#endif + + void dump(std::vector&) const; + + void createBranch(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; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + 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; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + 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; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > 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; + + // 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; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/ios/include/SPIRV/SpvTools.h b/ios/include/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/ios/include/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// 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 + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/ios/include/SPIRV/bitutils.h b/ios/include/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/ios/include/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// 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/ios/include/SPIRV/disassemble.h b/ios/include/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/ios/include/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// 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 + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/ios/include/SPIRV/doc.h b/ios/include/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/ios/include/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// 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, + 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, + + 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(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + 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: + int typePresent : 1; + int 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/ios/include/SPIRV/hex_float.h b/ios/include/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/ios/include/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// 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 + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#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/ios/include/SPIRV/spirv.hpp b/ios/include/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/ios/include/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-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. + +// 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 +// +// - 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 +// +// 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 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +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, + 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, + 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, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + 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, + 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, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + 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, + 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, + 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, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + 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, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + 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, + 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, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + 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, + 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, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + 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, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + 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, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + 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, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +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 { + 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, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +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 { + 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, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + 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, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + 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, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +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 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, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + 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, + 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, + 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, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +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 OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *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 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 OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *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 OpTypeAccelerationStructureNV: *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 OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *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 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 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; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/ios/include/SPIRV/spvIR.h b/ios/include/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/ios/include/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// 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 + +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 addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + 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; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 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]); + } + +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. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + 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; } + const std::vector >& getInstructions() const { + 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 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 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, 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(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // 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); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + 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 +}; + +// +// 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, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + 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); + } +} + +__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 diff --git a/ios/include/glslang/Include/BaseTypes.h b/ios/include/glslang/Include/BaseTypes.h new file mode 100644 index 00000000..816b1794 --- /dev/null +++ b/ios/include/glslang/Include/BaseTypes.h @@ -0,0 +1,565 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, 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. +// + +#ifndef _BASICTYPES_INCLUDED_ +#define _BASICTYPES_INCLUDED_ + +namespace glslang { + +// +// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this. +// +enum TBasicType { + EbtVoid, + EbtFloat, + EbtDouble, + EbtFloat16, + EbtInt8, + EbtUint8, + EbtInt16, + EbtUint16, + EbtInt, + EbtUint, + EbtInt64, + EbtUint64, + EbtBool, + EbtAtomicUint, + EbtSampler, + EbtStruct, + EbtBlock, + EbtAccStruct, + EbtReference, + EbtRayQuery, + + // HLSL types that live only temporarily. + EbtString, + + EbtNumTypes +}; + +// +// Storage qualifiers. Should align with different kinds of storage or +// resource or GLSL storage qualifier. Expansion is deprecated. +// +// N.B.: You probably DON'T want to add anything here, but rather just add it +// to the built-in variables. See the comment above TBuiltInVariable. +// +// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc. +// DO NOT follow the design pattern of, say EvqInstanceId, etc. +// +enum TStorageQualifier { + EvqTemporary, // For temporaries (within a function), read/write + EvqGlobal, // For globals read/write + EvqConst, // User-defined constant values, will be semantically constant and constant folded + EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) + EvqUniform, // read only, shared with app + EvqBuffer, // read/write, shared with app + EvqShared, // compute shader's read/write 'shared' qualifier + + EvqPayload, + EvqPayloadIn, + EvqHitAttr, + EvqCallableData, + EvqCallableDataIn, + + // parameters + EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter + EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter + EvqInOut, + EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics + + // built-ins read by vertex shader + EvqVertexId, + EvqInstanceId, + + // built-ins written by vertex shader + EvqPosition, + EvqPointSize, + EvqClipVertex, + + // built-ins read by fragment shader + EvqFace, + EvqFragCoord, + EvqPointCoord, + + // built-ins written by fragment shader + EvqFragColor, + EvqFragDepth, + + // end of list + EvqLast +}; + +// +// Subcategories of the TStorageQualifier, simply to give a direct mapping +// between built-in variable names and an numerical value (the enum). +// +// For backward compatibility, there is some redundancy between the +// TStorageQualifier and these. Existing members should both be maintained accurately. +// However, any new built-in variable (and any existing non-redundant one) +// must follow the pattern that the specific built-in is here, and only its +// general qualifier is in TStorageQualifier. +// +// Something like gl_Position, which is sometimes 'in' and sometimes 'out' +// shows up as two different built-in variables in a single stage, but +// only has a single enum in TBuiltInVariable, so both the +// TStorageQualifier and the TBuitinVariable are needed to distinguish +// between them. +// +enum TBuiltInVariable { + EbvNone, + EbvNumWorkGroups, + EbvWorkGroupSize, + EbvWorkGroupId, + EbvLocalInvocationId, + EbvGlobalInvocationId, + EbvLocalInvocationIndex, + EbvNumSubgroups, + EbvSubgroupID, + EbvSubGroupSize, + EbvSubGroupInvocation, + EbvSubGroupEqMask, + EbvSubGroupGeMask, + EbvSubGroupGtMask, + EbvSubGroupLeMask, + EbvSubGroupLtMask, + EbvSubgroupSize2, + EbvSubgroupInvocation2, + EbvSubgroupEqMask2, + EbvSubgroupGeMask2, + EbvSubgroupGtMask2, + EbvSubgroupLeMask2, + EbvSubgroupLtMask2, + EbvVertexId, + EbvInstanceId, + EbvVertexIndex, + EbvInstanceIndex, + EbvBaseVertex, + EbvBaseInstance, + EbvDrawId, + EbvPosition, + EbvPointSize, + EbvClipVertex, + EbvClipDistance, + EbvCullDistance, + EbvNormal, + EbvVertex, + EbvMultiTexCoord0, + EbvMultiTexCoord1, + EbvMultiTexCoord2, + EbvMultiTexCoord3, + EbvMultiTexCoord4, + EbvMultiTexCoord5, + EbvMultiTexCoord6, + EbvMultiTexCoord7, + EbvFrontColor, + EbvBackColor, + EbvFrontSecondaryColor, + EbvBackSecondaryColor, + EbvTexCoord, + EbvFogFragCoord, + EbvInvocationId, + EbvPrimitiveId, + EbvLayer, + EbvViewportIndex, + EbvPatchVertices, + EbvTessLevelOuter, + EbvTessLevelInner, + EbvBoundingBox, + EbvTessCoord, + EbvColor, + EbvSecondaryColor, + EbvFace, + EbvFragCoord, + EbvPointCoord, + EbvFragColor, + EbvFragData, + EbvFragDepth, + EbvFragStencilRef, + EbvSampleId, + EbvSamplePosition, + EbvSampleMask, + EbvHelperInvocation, + + EbvBaryCoordNoPersp, + EbvBaryCoordNoPerspCentroid, + EbvBaryCoordNoPerspSample, + EbvBaryCoordSmooth, + EbvBaryCoordSmoothCentroid, + EbvBaryCoordSmoothSample, + EbvBaryCoordPullModel, + + EbvViewIndex, + EbvDeviceIndex, + + EbvFragSizeEXT, + EbvFragInvocationCountEXT, + + EbvViewportMaskNV, + EbvSecondaryPositionNV, + EbvSecondaryViewportMaskNV, + EbvPositionPerViewNV, + EbvViewportMaskPerViewNV, + EbvFragFullyCoveredNV, + EbvFragmentSizeNV, + EbvInvocationsPerPixelNV, + // ray tracing + EbvLaunchId, + EbvLaunchSize, + EbvInstanceCustomIndex, + EbvGeometryIndex, + EbvWorldRayOrigin, + EbvWorldRayDirection, + EbvObjectRayOrigin, + EbvObjectRayDirection, + EbvRayTmin, + EbvRayTmax, + EbvHitT, + EbvHitKind, + EbvObjectToWorld, + EbvObjectToWorld3x4, + EbvWorldToObject, + EbvWorldToObject3x4, + EbvIncomingRayFlags, + // barycentrics + EbvBaryCoordNV, + EbvBaryCoordNoPerspNV, + // mesh shaders + EbvTaskCountNV, + EbvPrimitiveCountNV, + EbvPrimitiveIndicesNV, + EbvClipDistancePerViewNV, + EbvCullDistancePerViewNV, + EbvLayerPerViewNV, + EbvMeshViewCountNV, + EbvMeshViewIndicesNV, + + // sm builtins + EbvWarpsPerSM, + EbvSMCount, + EbvWarpID, + EbvSMID, + + // HLSL built-ins that live only temporarily, until they get remapped + // to one of the above. + EbvFragDepthGreater, + EbvFragDepthLesser, + EbvGsOutputStream, + EbvOutputPatch, + EbvInputPatch, + + // structbuffer types + EbvAppendConsume, // no need to differentiate append and consume + EbvRWStructuredBuffer, + EbvStructuredBuffer, + EbvByteAddressBuffer, + EbvRWByteAddressBuffer, + + EbvLast +}; + +// In this enum, order matters; users can assume higher precision is a bigger value +// and EpqNone is 0. +enum TPrecisionQualifier { + EpqNone = 0, + EpqLow, + EpqMedium, + EpqHigh +}; + +#ifdef GLSLANG_WEB +__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; } +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; } +#else +// These will show up in error messages +__inline const char* GetStorageQualifierString(TStorageQualifier q) +{ + switch (q) { + case EvqTemporary: return "temp"; break; + case EvqGlobal: return "global"; break; + case EvqConst: return "const"; break; + case EvqConstReadOnly: return "const (read only)"; break; + case EvqVaryingIn: return "in"; break; + case EvqVaryingOut: return "out"; break; + case EvqUniform: return "uniform"; break; + case EvqBuffer: return "buffer"; break; + case EvqShared: return "shared"; break; + case EvqIn: return "in"; break; + case EvqOut: return "out"; break; + case EvqInOut: return "inout"; break; + case EvqVertexId: return "gl_VertexId"; break; + case EvqInstanceId: return "gl_InstanceId"; break; + case EvqPosition: return "gl_Position"; break; + case EvqPointSize: return "gl_PointSize"; break; + case EvqClipVertex: return "gl_ClipVertex"; break; + case EvqFace: return "gl_FrontFacing"; break; + case EvqFragCoord: return "gl_FragCoord"; break; + case EvqPointCoord: return "gl_PointCoord"; break; + case EvqFragColor: return "fragColor"; break; + case EvqFragDepth: return "gl_FragDepth"; break; + case EvqPayload: return "rayPayloadNV"; break; + case EvqPayloadIn: return "rayPayloadInNV"; break; + case EvqHitAttr: return "hitAttributeNV"; break; + case EvqCallableData: return "callableDataNV"; break; + case EvqCallableDataIn: return "callableDataInNV"; break; + default: return "unknown qualifier"; + } +} + +__inline const char* GetBuiltInVariableString(TBuiltInVariable v) +{ + switch (v) { + case EbvNone: return ""; + case EbvNumWorkGroups: return "NumWorkGroups"; + case EbvWorkGroupSize: return "WorkGroupSize"; + case EbvWorkGroupId: return "WorkGroupID"; + case EbvLocalInvocationId: return "LocalInvocationID"; + case EbvGlobalInvocationId: return "GlobalInvocationID"; + case EbvLocalInvocationIndex: return "LocalInvocationIndex"; + case EbvNumSubgroups: return "NumSubgroups"; + case EbvSubgroupID: return "SubgroupID"; + case EbvSubGroupSize: return "SubGroupSize"; + case EbvSubGroupInvocation: return "SubGroupInvocation"; + case EbvSubGroupEqMask: return "SubGroupEqMask"; + case EbvSubGroupGeMask: return "SubGroupGeMask"; + case EbvSubGroupGtMask: return "SubGroupGtMask"; + case EbvSubGroupLeMask: return "SubGroupLeMask"; + case EbvSubGroupLtMask: return "SubGroupLtMask"; + case EbvSubgroupSize2: return "SubgroupSize"; + case EbvSubgroupInvocation2: return "SubgroupInvocationID"; + case EbvSubgroupEqMask2: return "SubgroupEqMask"; + case EbvSubgroupGeMask2: return "SubgroupGeMask"; + case EbvSubgroupGtMask2: return "SubgroupGtMask"; + case EbvSubgroupLeMask2: return "SubgroupLeMask"; + case EbvSubgroupLtMask2: return "SubgroupLtMask"; + case EbvVertexId: return "VertexId"; + case EbvInstanceId: return "InstanceId"; + case EbvVertexIndex: return "VertexIndex"; + case EbvInstanceIndex: return "InstanceIndex"; + case EbvBaseVertex: return "BaseVertex"; + case EbvBaseInstance: return "BaseInstance"; + case EbvDrawId: return "DrawId"; + case EbvPosition: return "Position"; + case EbvPointSize: return "PointSize"; + case EbvClipVertex: return "ClipVertex"; + case EbvClipDistance: return "ClipDistance"; + case EbvCullDistance: return "CullDistance"; + case EbvNormal: return "Normal"; + case EbvVertex: return "Vertex"; + case EbvMultiTexCoord0: return "MultiTexCoord0"; + case EbvMultiTexCoord1: return "MultiTexCoord1"; + case EbvMultiTexCoord2: return "MultiTexCoord2"; + case EbvMultiTexCoord3: return "MultiTexCoord3"; + case EbvMultiTexCoord4: return "MultiTexCoord4"; + case EbvMultiTexCoord5: return "MultiTexCoord5"; + case EbvMultiTexCoord6: return "MultiTexCoord6"; + case EbvMultiTexCoord7: return "MultiTexCoord7"; + case EbvFrontColor: return "FrontColor"; + case EbvBackColor: return "BackColor"; + case EbvFrontSecondaryColor: return "FrontSecondaryColor"; + case EbvBackSecondaryColor: return "BackSecondaryColor"; + case EbvTexCoord: return "TexCoord"; + case EbvFogFragCoord: return "FogFragCoord"; + case EbvInvocationId: return "InvocationID"; + case EbvPrimitiveId: return "PrimitiveID"; + case EbvLayer: return "Layer"; + case EbvViewportIndex: return "ViewportIndex"; + case EbvPatchVertices: return "PatchVertices"; + case EbvTessLevelOuter: return "TessLevelOuter"; + case EbvTessLevelInner: return "TessLevelInner"; + case EbvBoundingBox: return "BoundingBox"; + case EbvTessCoord: return "TessCoord"; + case EbvColor: return "Color"; + case EbvSecondaryColor: return "SecondaryColor"; + case EbvFace: return "Face"; + case EbvFragCoord: return "FragCoord"; + case EbvPointCoord: return "PointCoord"; + case EbvFragColor: return "FragColor"; + case EbvFragData: return "FragData"; + case EbvFragDepth: return "FragDepth"; + case EbvFragStencilRef: return "FragStencilRef"; + case EbvSampleId: return "SampleId"; + case EbvSamplePosition: return "SamplePosition"; + case EbvSampleMask: return "SampleMaskIn"; + case EbvHelperInvocation: return "HelperInvocation"; + + case EbvBaryCoordNoPersp: return "BaryCoordNoPersp"; + case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid"; + case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample"; + case EbvBaryCoordSmooth: return "BaryCoordSmooth"; + case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid"; + case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample"; + case EbvBaryCoordPullModel: return "BaryCoordPullModel"; + + case EbvViewIndex: return "ViewIndex"; + case EbvDeviceIndex: return "DeviceIndex"; + + case EbvFragSizeEXT: return "FragSizeEXT"; + case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; + + case EbvViewportMaskNV: return "ViewportMaskNV"; + case EbvSecondaryPositionNV: return "SecondaryPositionNV"; + case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; + case EbvPositionPerViewNV: return "PositionPerViewNV"; + case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; + case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; + case EbvFragmentSizeNV: return "FragmentSizeNV"; + case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; + case EbvLaunchId: return "LaunchIdNV"; + case EbvLaunchSize: return "LaunchSizeNV"; + case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; + case EbvGeometryIndex: return "GeometryIndexEXT"; + case EbvWorldRayOrigin: return "WorldRayOriginNV"; + case EbvWorldRayDirection: return "WorldRayDirectionNV"; + case EbvObjectRayOrigin: return "ObjectRayOriginNV"; + case EbvObjectRayDirection: return "ObjectRayDirectionNV"; + case EbvRayTmin: return "ObjectRayTminNV"; + case EbvRayTmax: return "ObjectRayTmaxNV"; + case EbvHitT: return "HitTNV"; + case EbvHitKind: return "HitKindNV"; + case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; + case EbvObjectToWorld: return "ObjectToWorldNV"; + case EbvWorldToObject: return "WorldToObjectNV"; + + case EbvBaryCoordNV: return "BaryCoordNV"; + case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; + + case EbvTaskCountNV: return "TaskCountNV"; + case EbvPrimitiveCountNV: return "PrimitiveCountNV"; + case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV"; + case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV"; + case EbvCullDistancePerViewNV: return "CullDistancePerViewNV"; + case EbvLayerPerViewNV: return "LayerPerViewNV"; + case EbvMeshViewCountNV: return "MeshViewCountNV"; + case EbvMeshViewIndicesNV: return "MeshViewIndicesNV"; + + case EbvWarpsPerSM: return "WarpsPerSMNV"; + case EbvSMCount: return "SMCountNV"; + case EbvWarpID: return "WarpIDNV"; + case EbvSMID: return "SMIDNV"; + + default: return "unknown built-in variable"; + } +} + +__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) +{ + switch (p) { + case EpqNone: return ""; break; + case EpqLow: return "lowp"; break; + case EpqMedium: return "mediump"; break; + case EpqHigh: return "highp"; break; + default: return "unknown precision qualifier"; + } +} +#endif + +__inline bool isTypeSignedInt(TBasicType type) +{ + switch (type) { + case EbtInt8: + case EbtInt16: + case EbtInt: + case EbtInt64: + return true; + default: + return false; + } +} + +__inline bool isTypeUnsignedInt(TBasicType type) +{ + switch (type) { + case EbtUint8: + case EbtUint16: + case EbtUint: + case EbtUint64: + return true; + default: + return false; + } +} + +__inline bool isTypeInt(TBasicType type) +{ + return isTypeSignedInt(type) || isTypeUnsignedInt(type); +} + +__inline bool isTypeFloat(TBasicType type) +{ + switch (type) { + case EbtFloat: + case EbtDouble: + case EbtFloat16: + return true; + default: + return false; + } +} + +__inline int getTypeRank(TBasicType type) +{ + int res = -1; + switch(type) { + case EbtInt8: + case EbtUint8: + res = 0; + break; + case EbtInt16: + case EbtUint16: + res = 1; + break; + case EbtInt: + case EbtUint: + res = 2; + break; + case EbtInt64: + case EbtUint64: + res = 3; + break; + default: + assert(false); + break; + } + return res; +} + +} // end namespace glslang + +#endif // _BASICTYPES_INCLUDED_ diff --git a/ios/include/glslang/Include/Common.h b/ios/include/glslang/Include/Common.h new file mode 100644 index 00000000..733a790c --- /dev/null +++ b/ios/include/glslang/Include/Common.h @@ -0,0 +1,292 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 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 _COMMON_INCLUDED_ +#define _COMMON_INCLUDED_ + + +#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700) +#include +namespace std { +template +std::string to_string(const T& val) { + std::ostringstream os; + os << val; + return os.str(); +} +} +#endif + +#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API + #include + #ifndef snprintf + #define snprintf sprintf_s + #endif + #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args)) +#elif defined (solaris) + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#else + #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) + #include + #define UINT_PTR uintptr_t +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1800 + #include + inline long long int strtoll (const char* str, char** endptr, int base) + { + return _strtoi64(str, endptr, base); + } + inline unsigned long long int strtoull (const char* str, char** endptr, int base) + { + return _strtoui64(str, endptr, base); + } + inline long long int atoll (const char* str) + { + return strtoll(str, NULL, 10); + } +#endif + +#if defined(_MSC_VER) +#define strdup _strdup +#endif + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4786) // Don't warn about too long identifiers + #pragma warning(disable : 4514) // unused inline method + #pragma warning(disable : 4201) // nameless union +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PoolAlloc.h" + +// +// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. +// +#define POOL_ALLOCATOR_NEW_DELETE(A) \ + void* operator new(size_t s) { return (A).allocate(s); } \ + void* operator new(size_t, void *_Where) { return (_Where); } \ + void operator delete(void*) { } \ + void operator delete(void *, void *) { } \ + void* operator new[](size_t s) { return (A).allocate(s); } \ + void* operator new[](size_t, void *_Where) { return (_Where); } \ + void operator delete[](void*) { } \ + void operator delete[](void *, void *) { } + +namespace glslang { + + // + // Pool version of string. + // + typedef pool_allocator TStringAllocator; + typedef std::basic_string , TStringAllocator> TString; + +} // end namespace glslang + +// Repackage the std::hash for use by unordered map/set with a TString key. +namespace std { + + template<> struct hash { + std::size_t operator()(const glslang::TString& s) const + { + const unsigned _FNV_offset_basis = 2166136261U; + const unsigned _FNV_prime = 16777619U; + unsigned _Val = _FNV_offset_basis; + size_t _Count = s.size(); + const char* _First = s.c_str(); + for (size_t _Next = 0; _Next < _Count; ++_Next) + { + _Val ^= (unsigned)_First[_Next]; + _Val *= _FNV_prime; + } + + return _Val; + } + }; +} + +namespace glslang { + +inline TString* NewPoolTString(const char* s) +{ + void* memory = GetThreadPoolAllocator().allocate(sizeof(TString)); + return new(memory) TString(s); +} + +template inline T* NewPoolObject(T*) +{ + return new(GetThreadPoolAllocator().allocate(sizeof(T))) T; +} + +template inline T* NewPoolObject(T, int instances) +{ + return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances]; +} + +// +// Pool allocator versions of vectors, lists, and maps +// +template class TVector : public std::vector > { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + typedef typename std::vector >::size_type size_type; + TVector() : std::vector >() {} + TVector(const pool_allocator& a) : std::vector >(a) {} + TVector(size_type i) : std::vector >(i) {} + TVector(size_type i, const T& val) : std::vector >(i, val) {} +}; + +template class TList : public std::list > { +}; + +template > +class TMap : public std::map > > { +}; + +template , class PRED = std::equal_to > +class TUnorderedMap : public std::unordered_map > > { +}; + +// +// Persistent string memory. Should only be used for strings that survive +// across compiles/links. +// +typedef std::basic_string TPersistString; + +// +// templatized min and max functions. +// +template T Min(const T a, const T b) { return a < b ? a : b; } +template T Max(const T a, const T b) { return a > b ? a : b; } + +// +// Create a TString object from an integer. +// +#if defined _MSC_VER || defined MINGW_HAS_SECURE_API +inline const TString String(const int i, const int base = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + _itoa_s(i, text, sizeof(text), base); + return text; +} +#else +inline const TString String(const int i, const int /*base*/ = 10) +{ + char text[16]; // 32 bit ints are at most 10 digits in base 10 + + // we assume base 10 for all cases + snprintf(text, sizeof(text), "%d", i); + + return text; +} +#endif + +struct TSourceLoc { + void init() + { + name = nullptr; string = 0; line = 0; column = 0; + } + void init(int stringNum) { init(); string = stringNum; } + // Returns the name if it exists. Otherwise, returns the string number. + std::string getStringNameOrNum(bool quoteStringName = true) const + { + if (name != nullptr) { + TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name; + std::string ret_str(qstr.c_str()); + return ret_str; + } + return std::to_string((long long)string); + } + const char* getFilename() const + { + if (name == nullptr) + return nullptr; + return name->c_str(); + } + const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); } + TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr + int string; + int line; + int column; +}; + +class TPragmaTable : public TMap { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) +}; + +const int MaxTokenLength = 1024; + +template bool IsPow2(T powerOf2) +{ + if (powerOf2 <= 0) + return false; + + return (powerOf2 & (powerOf2 - 1)) == 0; +} + +// Round number up to a multiple of the given powerOf2, which is not +// a power, just a number that must be a power of 2. +template void RoundToPow2(T& number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + number = (number + powerOf2 - 1) & ~(powerOf2 - 1); +} + +template bool IsMultipleOfPow2(T number, int powerOf2) +{ + assert(IsPow2(powerOf2)); + return ! (number & (powerOf2 - 1)); +} + +} // end namespace glslang + +#endif // _COMMON_INCLUDED_ diff --git a/ios/include/glslang/Include/ConstantUnion.h b/ios/include/glslang/Include/ConstantUnion.h new file mode 100644 index 00000000..c4ffb857 --- /dev/null +++ b/ios/include/glslang/Include/ConstantUnion.h @@ -0,0 +1,974 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// +// 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 _CONSTANT_UNION_INCLUDED_ +#define _CONSTANT_UNION_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" + +namespace glslang { + +class TConstUnion { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnion() : iConst(0), type(EbtInt) { } + + void setI8Const(signed char i) + { + i8Const = i; + type = EbtInt8; + } + + void setU8Const(unsigned char u) + { + u8Const = u; + type = EbtUint8; + } + + void setI16Const(signed short i) + { + i16Const = i; + type = EbtInt16; + } + + void setU16Const(unsigned short u) + { + u16Const = u; + type = EbtUint16; + } + + void setIConst(int i) + { + iConst = i; + type = EbtInt; + } + + void setUConst(unsigned int u) + { + uConst = u; + type = EbtUint; + } + + void setI64Const(long long i64) + { + i64Const = i64; + type = EbtInt64; + } + + void setU64Const(unsigned long long u64) + { + u64Const = u64; + type = EbtUint64; + } + + void setDConst(double d) + { + dConst = d; + type = EbtDouble; + } + + void setBConst(bool b) + { + bConst = b; + type = EbtBool; + } + + void setSConst(const TString* s) + { + sConst = s; + type = EbtString; + } + + signed char getI8Const() const { return i8Const; } + unsigned char getU8Const() const { return u8Const; } + signed short getI16Const() const { return i16Const; } + unsigned short getU16Const() const { return u16Const; } + int getIConst() const { return iConst; } + unsigned int getUConst() const { return uConst; } + long long getI64Const() const { return i64Const; } + unsigned long long getU64Const() const { return u64Const; } + double getDConst() const { return dConst; } + bool getBConst() const { return bConst; } + const TString* getSConst() const { return sConst; } + + bool operator==(const signed char i) const + { + if (i == i8Const) + return true; + + return false; + } + + bool operator==(const unsigned char u) const + { + if (u == u8Const) + return true; + + return false; + } + + bool operator==(const signed short i) const + { + if (i == i16Const) + return true; + + return false; + } + + bool operator==(const unsigned short u) const + { + if (u == u16Const) + return true; + + return false; + } + + bool operator==(const int i) const + { + if (i == iConst) + return true; + + return false; + } + + bool operator==(const unsigned int u) const + { + if (u == uConst) + return true; + + return false; + } + + bool operator==(const long long i64) const + { + if (i64 == i64Const) + return true; + + return false; + } + + bool operator==(const unsigned long long u64) const + { + if (u64 == u64Const) + return true; + + return false; + } + + bool operator==(const double d) const + { + if (d == dConst) + return true; + + return false; + } + + bool operator==(const bool b) const + { + if (b == bConst) + return true; + + return false; + } + + bool operator==(const TConstUnion& constant) const + { + if (constant.type != type) + return false; + + switch (type) { + case EbtInt: + if (constant.iConst == iConst) + return true; + + break; + case EbtUint: + if (constant.uConst == uConst) + return true; + + break; + case EbtBool: + if (constant.bConst == bConst) + return true; + + break; + case EbtDouble: + if (constant.dConst == dConst) + return true; + + break; + +#ifndef GLSLANG_WEB + case EbtInt16: + if (constant.i16Const == i16Const) + return true; + + break; + case EbtUint16: + if (constant.u16Const == u16Const) + return true; + + break; + case EbtInt8: + if (constant.i8Const == i8Const) + return true; + + break; + case EbtUint8: + if (constant.u8Const == u8Const) + return true; + + break; + case EbtInt64: + if (constant.i64Const == i64Const) + return true; + + break; + case EbtUint64: + if (constant.u64Const == u64Const) + return true; + + break; +#endif + default: + assert(false && "Default missing"); + } + + return false; + } + + bool operator!=(const signed char i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned char u) const + { + return !operator==(u); + } + + bool operator!=(const signed short i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned short u) const + { + return !operator==(u); + } + + bool operator!=(const int i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } + + bool operator!=(const long long i) const + { + return !operator==(i); + } + + bool operator!=(const unsigned long long u) const + { + return !operator==(u); + } + + bool operator!=(const float f) const + { + return !operator==(f); + } + + bool operator!=(const bool b) const + { + return !operator==(b); + } + + bool operator!=(const TConstUnion& constant) const + { + return !operator==(constant); + } + + bool operator>(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { + case EbtInt: + if (iConst > constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst > constant.uConst) + return true; + + return false; + case EbtDouble: + if (dConst > constant.dConst) + return true; + + return false; +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const > constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const > constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const > constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const > constant.u16Const) + return true; + + return false; + case EbtInt64: + if (i64Const > constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const > constant.u64Const) + return true; + + return false; +#endif + default: + assert(false && "Default missing"); + return false; + } + } + + bool operator<(const TConstUnion& constant) const + { + assert(type == constant.type); + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + if (i8Const < constant.i8Const) + return true; + + return false; + case EbtUint8: + if (u8Const < constant.u8Const) + return true; + + return false; + case EbtInt16: + if (i16Const < constant.i16Const) + return true; + + return false; + case EbtUint16: + if (u16Const < constant.u16Const) + return true; + return false; + case EbtInt64: + if (i64Const < constant.i64Const) + return true; + + return false; + case EbtUint64: + if (u64Const < constant.u64Const) + return true; + + return false; +#endif + case EbtDouble: + if (dConst < constant.dConst) + return true; + + return false; + case EbtInt: + if (iConst < constant.iConst) + return true; + + return false; + case EbtUint: + if (uConst < constant.uConst) + return true; + + return false; + default: + assert(false && "Default missing"); + return false; + } + } + + TConstUnion operator+(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst + constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator-(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst - constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator*(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst * constant.uConst); break; + case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator%(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst % constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break; + case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break; + case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break; + case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator>>(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; +#ifndef GLSLANG_WEB + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator<<(const TConstUnion& constant) const + { + TConstUnion returnValue; + switch (type) { +#ifndef GLSLANG_WEB + case EbtInt8: + switch (constant.type) { + case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break; + case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break; + case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break; + case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break; + case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break; + case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break; + case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break; + case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint8: + switch (constant.type) { + case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break; + case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break; + case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break; + case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break; + case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break; + case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break; + case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt16: + switch (constant.type) { + case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break; + case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break; + case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break; + case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break; + case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break; + case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break; + case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint16: + switch (constant.type) { + case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break; + case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break; + case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break; + case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break; + case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break; + case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break; + case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtInt64: + switch (constant.type) { + case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break; + case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break; + case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break; + case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break; + case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break; + case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break; + case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break; + case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; + case EbtUint64: + switch (constant.type) { + case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break; + case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break; + case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break; + case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break; + case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break; + case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break; + case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break; + default: assert(false && "Default missing"); + } + break; +#endif + case EbtInt: + switch (constant.type) { + case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break; + case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break; + case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break; + case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break; + case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; + case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + case EbtUint: + switch (constant.type) { + case EbtInt: returnValue.setUConst(uConst << constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break; + case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break; + case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break; + case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break; + case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; + case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst & constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator|(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst | constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator^(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break; + case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break; + case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break; + case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break; + case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; + case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator~() const + { + TConstUnion returnValue; + switch (type) { + case EbtInt: returnValue.setIConst(~iConst); break; + case EbtUint: returnValue.setUConst(~uConst); break; +#ifndef GLSLANG_WEB + case EbtInt8: returnValue.setI8Const(~i8Const); break; + case EbtUint8: returnValue.setU8Const(~u8Const); break; + case EbtInt16: returnValue.setI16Const(~i16Const); break; + case EbtUint16: returnValue.setU16Const(~u16Const); break; + case EbtInt64: returnValue.setI64Const(~i64Const); break; + case EbtUint64: returnValue.setU64Const(~u64Const); break; +#endif + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator&&(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TConstUnion operator||(const TConstUnion& constant) const + { + TConstUnion returnValue; + assert(type == constant.type); + switch (type) { + case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; + default: assert(false && "Default missing"); + } + + return returnValue; + } + + TBasicType getType() const { return type; } + +private: + union { + signed char i8Const; // used for i8vec, scalar int8s + unsigned char u8Const; // used for u8vec, scalar uint8s + signed short i16Const; // used for i16vec, scalar int16s + unsigned short u16Const; // used for u16vec, scalar uint16s + int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints + long long i64Const; // used for i64vec, scalar int64s + unsigned long long u64Const; // used for u64vec, scalar uint64s + bool bConst; // used for bvec, scalar bools + double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles + const TString* sConst; // string constant + }; + + TBasicType type; +}; + +// Encapsulate having a pointer to an array of TConstUnion, +// which only needs to be allocated if its size is going to be +// bigger than 0. +// +// One convenience is being able to use [] to go inside the array, instead +// of C++ assuming it as an array of pointers to vectors. +// +// General usage is that the size is known up front, and it is +// created once with the proper size. +// +class TConstUnionArray { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TConstUnionArray() : unionArray(nullptr) { } + virtual ~TConstUnionArray() { } + + explicit TConstUnionArray(int size) + { + if (size == 0) + unionArray = nullptr; + else + unionArray = new TConstUnionVector(size); + } + TConstUnionArray(const TConstUnionArray& a) = default; + TConstUnionArray(const TConstUnionArray& a, int start, int size) + { + unionArray = new TConstUnionVector(size); + for (int i = 0; i < size; ++i) + (*unionArray)[i] = a[start + i]; + } + + // Use this constructor for a smear operation + TConstUnionArray(int size, const TConstUnion& val) + { + unionArray = new TConstUnionVector(size, val); + } + + int size() const { return unionArray ? (int)unionArray->size() : 0; } + TConstUnion& operator[](size_t index) { return (*unionArray)[index]; } + const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; } + bool operator==(const TConstUnionArray& rhs) const + { + // this includes the case that both are unallocated + if (unionArray == rhs.unionArray) + return true; + + if (! unionArray || ! rhs.unionArray) + return false; + + return *unionArray == *rhs.unionArray; + } + bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); } + + double dot(const TConstUnionArray& rhs) + { + assert(rhs.unionArray->size() == unionArray->size()); + double sum = 0.0; + + for (size_t comp = 0; comp < unionArray->size(); ++comp) + sum += (*this)[comp].getDConst() * rhs[comp].getDConst(); + + return sum; + } + + bool empty() const { return unionArray == nullptr; } + +protected: + typedef TVector TConstUnionVector; + TConstUnionVector* unionArray; +}; + +} // end namespace glslang + +#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/ios/include/glslang/Include/InfoSink.h b/ios/include/glslang/Include/InfoSink.h new file mode 100644 index 00000000..dceb603c --- /dev/null +++ b/ios/include/glslang/Include/InfoSink.h @@ -0,0 +1,144 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// 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 _INFOSINK_INCLUDED_ +#define _INFOSINK_INCLUDED_ + +#include "../Include/Common.h" +#include + +namespace glslang { + +// +// TPrefixType is used to centralize how info log messages start. +// See below. +// +enum TPrefixType { + EPrefixNone, + EPrefixWarning, + EPrefixError, + EPrefixInternalError, + EPrefixUnimplemented, + EPrefixNote +}; + +enum TOutputStream { + ENull = 0, + EDebugger = 0x01, + EStdOut = 0x02, + EString = 0x04, +}; +// +// Encapsulate info logs for all objects that have them. +// +// The methods are a general set of tools for getting a variety of +// messages and types inserted into the log. +// +class TInfoSinkBase { +public: + TInfoSinkBase() : outputStream(4) {} + void erase() { sink.erase(); } + TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } + TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } + TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; } + TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size]; + snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n); + append(buf); + return *this; } + TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } + TInfoSinkBase& operator+(const char* s) { append(s); return *this; } + const char* c_str() const { return sink.c_str(); } + void prefix(TPrefixType message) { + switch(message) { + case EPrefixNone: break; + case EPrefixWarning: append("WARNING: "); break; + case EPrefixError: append("ERROR: "); break; + case EPrefixInternalError: append("INTERNAL ERROR: "); break; + case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; + case EPrefixNote: append("NOTE: "); break; + default: append("UNKNOWN ERROR: "); break; + } + } + void location(const TSourceLoc& loc) { + const int maxSize = 24; + char locText[maxSize]; + snprintf(locText, maxSize, ":%d", loc.line); + append(loc.getStringNameOrNum(false).c_str()); + append(locText); + append(": "); + } + void message(TPrefixType message, const char* s) { + prefix(message); + append(s); + append("\n"); + } + void message(TPrefixType message, const char* s, const TSourceLoc& loc) { + prefix(message); + location(loc); + append(s); + append("\n"); + } + + void setOutputStream(int output = 4) + { + outputStream = output; + } + +protected: + void append(const char* s); + + void append(int count, char c); + void append(const TPersistString& t); + void append(const TString& t); + + void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) + sink.reserve(sink.capacity() + sink.capacity() / 2); } + void appendToStream(const char* s); + TPersistString sink; + int outputStream; +}; + +} // end namespace glslang + +class TInfoSink { +public: + glslang::TInfoSinkBase info; + glslang::TInfoSinkBase debug; +}; + +#endif // _INFOSINK_INCLUDED_ diff --git a/ios/include/glslang/Include/InitializeGlobals.h b/ios/include/glslang/Include/InitializeGlobals.h new file mode 100644 index 00000000..95d0a40e --- /dev/null +++ b/ios/include/glslang/Include/InitializeGlobals.h @@ -0,0 +1,44 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// 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 __INITIALIZE_GLOBALS_INCLUDED_ +#define __INITIALIZE_GLOBALS_INCLUDED_ + +namespace glslang { + +bool InitializePoolIndex(); + +} // end namespace glslang + +#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/ios/include/glslang/Include/PoolAlloc.h b/ios/include/glslang/Include/PoolAlloc.h new file mode 100644 index 00000000..b8eccb88 --- /dev/null +++ b/ios/include/glslang/Include/PoolAlloc.h @@ -0,0 +1,316 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 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 _POOLALLOC_INCLUDED_ +#define _POOLALLOC_INCLUDED_ + +#ifdef _DEBUG +# define GUARD_BLOCKS // define to enable guard block sanity checking +#endif + +// +// This header defines an allocator that can be used to efficiently +// allocate a large number of small requests for heap memory, with the +// intention that they are not individually deallocated, but rather +// collectively deallocated at one time. +// +// This simultaneously +// +// * Makes each individual allocation much more efficient; the +// typical allocation is trivial. +// * Completely avoids the cost of doing individual deallocation. +// * Saves the trouble of tracking down and plugging a large class of leaks. +// +// Individual classes can use this allocator by supplying their own +// new and delete methods. +// +// STL containers can use this allocator by using the pool_allocator +// class as the allocator (second) template argument. +// + +#include +#include +#include + +namespace glslang { + +// If we are using guard blocks, we must track each individual +// allocation. If we aren't using guard blocks, these +// never get instantiated, so won't have any impact. +// + +class TAllocation { +public: + TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) : + size(size), mem(mem), prevAlloc(prev) { + // Allocations are bracketed: + // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] + // This would be cleaner with if (guardBlockSize)..., but that + // makes the compiler print warnings about 0 length memsets, + // even with the if() protecting them. +# ifdef GUARD_BLOCKS + memset(preGuard(), guardBlockBeginVal, guardBlockSize); + memset(data(), userDataFill, size); + memset(postGuard(), guardBlockEndVal, guardBlockSize); +# endif + } + + void check() const { + checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); + checkGuardBlock(postGuard(), guardBlockEndVal, "after"); + } + + void checkAllocList() const; + + // Return total size needed to accommodate user buffer of 'size', + // plus our tracking data. + inline static size_t allocationSize(size_t size) { + return size + 2 * guardBlockSize + headerSize(); + } + + // Offset from surrounding buffer to get to user data buffer. + inline static unsigned char* offsetAllocation(unsigned char* m) { + return m + guardBlockSize + headerSize(); + } + +private: + void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; + + // Find offsets to pre and post guard blocks, and user data buffer + unsigned char* preGuard() const { return mem + headerSize(); } + unsigned char* data() const { return preGuard() + guardBlockSize; } + unsigned char* postGuard() const { return data() + size; } + + size_t size; // size of the user data area + unsigned char* mem; // beginning of our allocation (pts to header) + TAllocation* prevAlloc; // prior allocation in the chain + + const static unsigned char guardBlockBeginVal; + const static unsigned char guardBlockEndVal; + const static unsigned char userDataFill; + + const static size_t guardBlockSize; +# ifdef GUARD_BLOCKS + inline static size_t headerSize() { return sizeof(TAllocation); } +# else + inline static size_t headerSize() { return 0; } +# endif +}; + +// +// There are several stacks. One is to track the pushing and popping +// of the user, and not yet implemented. The others are simply a +// repositories of free pages or used pages. +// +// Page stacks are linked together with a simple header at the beginning +// of each allocation obtained from the underlying OS. Multi-page allocations +// are returned to the OS. Individual page allocations are kept for future +// re-use. +// +// The "page size" used is not, nor must it match, the underlying OS +// page size. But, having it be about that size or equal to a set of +// pages is likely most optimal. +// +class TPoolAllocator { +public: + TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); + + // + // Don't call the destructor just to free up the memory, call pop() + // + ~TPoolAllocator(); + + // + // Call push() to establish a new place to pop memory too. Does not + // have to be called to get things started. + // + void push(); + + // + // Call pop() to free all memory allocated since the last call to push(), + // or if no last call to push, frees all memory since first allocation. + // + void pop(); + + // + // Call popAll() to free all memory allocated. + // + void popAll(); + + // + // Call allocate() to actually acquire memory. Returns 0 if no memory + // available, otherwise a properly aligned pointer to 'numBytes' of memory. + // + void* allocate(size_t numBytes); + + // + // There is no deallocate. The point of this class is that + // deallocation can be skipped by the user of it, as the model + // of use is to simultaneously deallocate everything at once + // by calling pop(), and to not have to solve memory leak problems. + // + +protected: + friend struct tHeader; + + struct tHeader { + tHeader(tHeader* nextPage, size_t pageCount) : +#ifdef GUARD_BLOCKS + lastAllocation(0), +#endif + nextPage(nextPage), pageCount(pageCount) { } + + ~tHeader() { +#ifdef GUARD_BLOCKS + if (lastAllocation) + lastAllocation->checkAllocList(); +#endif + } + +#ifdef GUARD_BLOCKS + TAllocation* lastAllocation; +#endif + tHeader* nextPage; + size_t pageCount; + }; + + struct tAllocState { + size_t offset; + tHeader* page; + }; + typedef std::vector tAllocStack; + + // Track allocations if and only if we're using guard blocks +#ifndef GUARD_BLOCKS + void* initializeAllocation(tHeader*, unsigned char* memory, size_t) { +#else + void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { + new(memory) TAllocation(numBytes, memory, block->lastAllocation); + block->lastAllocation = reinterpret_cast(memory); +#endif + + // This is optimized entirely away if GUARD_BLOCKS is not defined. + return TAllocation::offsetAllocation(memory); + } + + size_t pageSize; // granularity of allocation from the OS + size_t alignment; // all returned allocations will be aligned at + // this granularity, which will be a power of 2 + size_t alignmentMask; + size_t headerSkip; // amount of memory to skip to make room for the + // header (basically, size of header, rounded + // up to make it aligned + size_t currentPageOffset; // next offset in top of inUseList to allocate from + tHeader* freeList; // list of popped memory + tHeader* inUseList; // list of all memory currently being used + tAllocStack stack; // stack of where to allocate from, to partition pool + + int numCalls; // just an interesting statistic + size_t totalBytes; // just an interesting statistic +private: + TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator + TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor +}; + +// +// There could potentially be many pools with pops happening at +// different times. But a simple use is to have a global pop +// with everyone using the same global allocator. +// +extern TPoolAllocator& GetThreadPoolAllocator(); +void SetThreadPoolAllocator(TPoolAllocator* poolAllocator); + +// +// This STL compatible allocator is intended to be used as the allocator +// parameter to templatized STL containers, like vector and map. +// +// It will use the pools for allocation, and not +// do any deallocation, but will still do destruction. +// +template +class pool_allocator { +public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T *pointer; + typedef const T *const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template + struct rebind { + typedef pool_allocator other; + }; + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + + pool_allocator() : allocator(GetThreadPoolAllocator()) { } + pool_allocator(TPoolAllocator& a) : allocator(a) { } + pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } + + template + pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } + + pointer allocate(size_type n) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + pointer allocate(size_type n, const void*) { + return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } + + void deallocate(void*, size_type) { } + void deallocate(pointer, size_type) { } + + pointer _Charalloc(size_t n) { + return reinterpret_cast(getAllocator().allocate(n)); } + + void construct(pointer p, const T& val) { new ((void *)p) T(val); } + void destroy(pointer p) { p->T::~T(); } + + bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } + bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } + + size_type max_size() const { return static_cast(-1) / sizeof(T); } + size_type max_size(int size) const { return static_cast(-1) / size; } + + TPoolAllocator& getAllocator() const { return allocator; } + +protected: + pool_allocator& operator=(const pool_allocator&) { return *this; } + TPoolAllocator& allocator; +}; + +} // end namespace glslang + +#endif // _POOLALLOC_INCLUDED_ diff --git a/ios/include/glslang/Include/ResourceLimits.h b/ios/include/glslang/Include/ResourceLimits.h new file mode 100644 index 00000000..106b21d9 --- /dev/null +++ b/ios/include/glslang/Include/ResourceLimits.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 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 _RESOURCE_LIMITS_INCLUDED_ +#define _RESOURCE_LIMITS_INCLUDED_ + +struct TLimits { + bool nonInductiveForLoops; + bool whileLoops; + bool doWhileLoops; + bool generalUniformIndexing; + bool generalAttributeMatrixVectorIndexing; + bool generalVaryingIndexing; + bool generalSamplerIndexing; + bool generalVariableIndexing; + bool generalConstantMatrixVectorIndexing; +}; + +struct TBuiltInResource { + int maxLights; + int maxClipPlanes; + int maxTextureUnits; + int maxTextureCoords; + int maxVertexAttribs; + int maxVertexUniformComponents; + int maxVaryingFloats; + int maxVertexTextureImageUnits; + int maxCombinedTextureImageUnits; + int maxTextureImageUnits; + int maxFragmentUniformComponents; + int maxDrawBuffers; + int maxVertexUniformVectors; + int maxVaryingVectors; + int maxFragmentUniformVectors; + int maxVertexOutputVectors; + int maxFragmentInputVectors; + int minProgramTexelOffset; + int maxProgramTexelOffset; + int maxClipDistances; + int maxComputeWorkGroupCountX; + int maxComputeWorkGroupCountY; + int maxComputeWorkGroupCountZ; + int maxComputeWorkGroupSizeX; + int maxComputeWorkGroupSizeY; + int maxComputeWorkGroupSizeZ; + int maxComputeUniformComponents; + int maxComputeTextureImageUnits; + int maxComputeImageUniforms; + int maxComputeAtomicCounters; + int maxComputeAtomicCounterBuffers; + int maxVaryingComponents; + int maxVertexOutputComponents; + int maxGeometryInputComponents; + int maxGeometryOutputComponents; + int maxFragmentInputComponents; + int maxImageUnits; + int maxCombinedImageUnitsAndFragmentOutputs; + int maxCombinedShaderOutputResources; + int maxImageSamples; + int maxVertexImageUniforms; + int maxTessControlImageUniforms; + int maxTessEvaluationImageUniforms; + int maxGeometryImageUniforms; + int maxFragmentImageUniforms; + int maxCombinedImageUniforms; + int maxGeometryTextureImageUnits; + int maxGeometryOutputVertices; + int maxGeometryTotalOutputComponents; + int maxGeometryUniformComponents; + int maxGeometryVaryingComponents; + int maxTessControlInputComponents; + int maxTessControlOutputComponents; + int maxTessControlTextureImageUnits; + int maxTessControlUniformComponents; + int maxTessControlTotalOutputComponents; + int maxTessEvaluationInputComponents; + int maxTessEvaluationOutputComponents; + int maxTessEvaluationTextureImageUnits; + int maxTessEvaluationUniformComponents; + int maxTessPatchComponents; + int maxPatchVertices; + int maxTessGenLevel; + int maxViewports; + int maxVertexAtomicCounters; + int maxTessControlAtomicCounters; + int maxTessEvaluationAtomicCounters; + int maxGeometryAtomicCounters; + int maxFragmentAtomicCounters; + int maxCombinedAtomicCounters; + int maxAtomicCounterBindings; + int maxVertexAtomicCounterBuffers; + int maxTessControlAtomicCounterBuffers; + int maxTessEvaluationAtomicCounterBuffers; + int maxGeometryAtomicCounterBuffers; + int maxFragmentAtomicCounterBuffers; + int maxCombinedAtomicCounterBuffers; + int maxAtomicCounterBufferSize; + int maxTransformFeedbackBuffers; + int maxTransformFeedbackInterleavedComponents; + int maxCullDistances; + int maxCombinedClipAndCullDistances; + int maxSamples; + int maxMeshOutputVerticesNV; + int maxMeshOutputPrimitivesNV; + int maxMeshWorkGroupSizeX_NV; + int maxMeshWorkGroupSizeY_NV; + int maxMeshWorkGroupSizeZ_NV; + int maxTaskWorkGroupSizeX_NV; + int maxTaskWorkGroupSizeY_NV; + int maxTaskWorkGroupSizeZ_NV; + int maxMeshViewCountNV; + + TLimits limits; +}; + +#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/ios/include/glslang/Include/ShHandle.h b/ios/include/glslang/Include/ShHandle.h new file mode 100644 index 00000000..df07bd8e --- /dev/null +++ b/ios/include/glslang/Include/ShHandle.h @@ -0,0 +1,176 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// 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 _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#define SH_EXPORTING +#include "../Public/ShaderLang.h" +#include "../MachineIndependent/Versions.h" +#include "InfoSink.h" + +class TCompiler; +class TLinker; +class TUniformMap; + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase() { pool = new glslang::TPoolAllocator; } + virtual ~TShHandleBase() { delete pool; } + virtual TCompiler* getAsCompiler() { return 0; } + virtual TLinker* getAsLinker() { return 0; } + virtual TUniformMap* getAsUniformMap() { return 0; } + virtual glslang::TPoolAllocator* getPool() const { return pool; } +private: + glslang::TPoolAllocator* pool; +}; + +// +// The base class for the machine dependent linker to derive from +// for managing where uniforms live. +// +class TUniformMap : public TShHandleBase { +public: + TUniformMap() { } + virtual ~TUniformMap() { } + virtual TUniformMap* getAsUniformMap() { return this; } + virtual int getLocation(const char* name) = 0; + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink infoSink; +}; + +class TIntermNode; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase { +public: + TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } + virtual ~TCompiler() { } + EShLanguage getLanguage() { return language; } + virtual TInfoSink& getInfoSink() { return infoSink; } + + virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0; + + virtual TCompiler* getAsCompiler() { return this; } + virtual bool linkable() { return haveValidObjectCode; } + + TInfoSink& infoSink; +protected: + TCompiler& operator=(TCompiler&); + + EShLanguage language; + bool haveValidObjectCode; +}; + +// +// Link operations are based on a list of compile results... +// +typedef glslang::TVector TCompilerList; +typedef glslang::TVector THandleList; + +// +// The base class for the machine dependent linker to derive from +// to manage the resulting executable. +// + +class TLinker : public TShHandleBase { +public: + TLinker(EShExecutable e, TInfoSink& iSink) : + infoSink(iSink), + executable(e), + haveReturnableObjectCode(false), + appAttributeBindings(0), + fixedAttributeBindings(0), + excludedAttributes(0), + excludedCount(0), + uniformBindings(0) { } + virtual TLinker* getAsLinker() { return this; } + virtual ~TLinker() { } + virtual bool link(TCompilerList&, TUniformMap*) = 0; + virtual bool link(THandleList&) { return false; } + virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } + virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } + virtual void getAttributeBindings(ShBindingTable const **t) const = 0; + virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } + virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } + virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here + virtual TInfoSink& getInfoSink() { return infoSink; } + TInfoSink& infoSink; +protected: + TLinker& operator=(TLinker&); + EShExecutable executable; + bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver + + const ShBindingTable* appAttributeBindings; + const ShBindingTable* fixedAttributeBindings; + const int* excludedAttributes; + int excludedCount; + ShBindingTable* uniformBindings; // created by the linker +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler(EShLanguage, int); + +TShHandleBase* ConstructLinker(EShExecutable, int); +TShHandleBase* ConstructBindings(); +void DeleteLinker(TShHandleBase*); +void DeleteBindingList(TShHandleBase* bindingList); + +TUniformMap* ConstructUniformMap(); +void DeleteCompiler(TCompiler*); + +void DeleteUniformMap(TUniformMap*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/ios/include/glslang/Include/Types.h b/ios/include/glslang/Include/Types.h new file mode 100644 index 00000000..b2c416d1 --- /dev/null +++ b/ios/include/glslang/Include/Types.h @@ -0,0 +1,2483 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, Inc. +// Copyright (C) 2015-2016 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. +// + +#ifndef _TYPES_INCLUDED +#define _TYPES_INCLUDED + +#include "../Include/Common.h" +#include "../Include/BaseTypes.h" +#include "../Public/ShaderLang.h" +#include "arrays.h" + +#include + +namespace glslang { + +const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded + +const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed +inline bool IsAnonymous(const TString& name) +{ + return name.compare(0, 5, AnonymousPrefix) == 0; +} + +// +// Details within a sampler type +// +enum TSamplerDim { + EsdNone, + Esd1D, + Esd2D, + Esd3D, + EsdCube, + EsdRect, + EsdBuffer, + EsdSubpass, // goes only with non-sampled image (image is true) + EsdNumDims +}; + +struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler + TBasicType type : 8; // type returned by sampler + TSamplerDim dim : 8; + bool arrayed : 1; + bool shadow : 1; + bool ms : 1; + bool image : 1; // image, combined should be false + bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler + bool sampler : 1; // true means a pure sampler, other fields should be clear() + +#ifdef GLSLANG_WEB + bool is1D() const { return false; } + bool isBuffer() const { return false; } + bool isRect() const { return false; } + bool isSubpass() const { return false; } + bool isCombined() const { return true; } + bool isImage() const { return false; } + bool isImageClass() const { return false; } + bool isMultiSample() const { return false; } + bool isExternal() const { return false; } + void setExternal(bool e) { } + bool isYuv() const { return false; } +#else + unsigned int vectorSize : 3; // vector return type size. + // Some languages support structures as sample results. Storing the whole structure in the + // TSampler is too large, so there is an index to a separate table. + static const unsigned structReturnIndexBits = 4; // number of index bits to use. + static const unsigned structReturnSlots = (1< TTypeList; + +typedef TVector TIdentifierList; + +// +// Following are a series of helper enums for managing layouts and qualifiers, +// used for TPublicType, TType, others. +// + +enum TLayoutPacking { + ElpNone, + ElpShared, // default, but different than saying nothing + ElpStd140, + ElpStd430, + ElpPacked, + ElpScalar, + ElpCount // If expanding, see bitfield width below +}; + +enum TLayoutMatrix { + ElmNone, + ElmRowMajor, + ElmColumnMajor, // default, but different than saying nothing + ElmCount // If expanding, see bitfield width below +}; + +// Union of geometry shader and tessellation shader geometry types. +// They don't go into TType, but rather have current state per shader or +// active parser type (TPublicType). +enum TLayoutGeometry { + ElgNone, + ElgPoints, + ElgLines, + ElgLinesAdjacency, + ElgLineStrip, + ElgTriangles, + ElgTrianglesAdjacency, + ElgTriangleStrip, + ElgQuads, + ElgIsolines, +}; + +enum TVertexSpacing { + EvsNone, + EvsEqual, + EvsFractionalEven, + EvsFractionalOdd +}; + +enum TVertexOrder { + EvoNone, + EvoCw, + EvoCcw +}; + +// Note: order matters, as type of format is done by comparison. +enum TLayoutFormat { + ElfNone, + + // Float image + ElfRgba32f, + ElfRgba16f, + ElfR32f, + ElfRgba8, + ElfRgba8Snorm, + + ElfEsFloatGuard, // to help with comparisons + + ElfRg32f, + ElfRg16f, + ElfR11fG11fB10f, + ElfR16f, + ElfRgba16, + ElfRgb10A2, + ElfRg16, + ElfRg8, + ElfR16, + ElfR8, + ElfRgba16Snorm, + ElfRg16Snorm, + ElfRg8Snorm, + ElfR16Snorm, + ElfR8Snorm, + + ElfFloatGuard, // to help with comparisons + + // Int image + ElfRgba32i, + ElfRgba16i, + ElfRgba8i, + ElfR32i, + + ElfEsIntGuard, // to help with comparisons + + ElfRg32i, + ElfRg16i, + ElfRg8i, + ElfR16i, + ElfR8i, + + ElfIntGuard, // to help with comparisons + + // Uint image + ElfRgba32ui, + ElfRgba16ui, + ElfRgba8ui, + ElfR32ui, + + ElfEsUintGuard, // to help with comparisons + + ElfRg32ui, + ElfRg16ui, + ElfRgb10a2ui, + ElfRg8ui, + ElfR16ui, + ElfR8ui, + + ElfCount +}; + +enum TLayoutDepth { + EldNone, + EldAny, + EldGreater, + EldLess, + EldUnchanged, + + EldCount +}; + +enum TBlendEquationShift { + // No 'EBlendNone': + // These are used as bit-shift amounts. A mask of such shifts will have type 'int', + // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. + EBlendMultiply, + EBlendScreen, + EBlendOverlay, + EBlendDarken, + EBlendLighten, + EBlendColordodge, + EBlendColorburn, + EBlendHardlight, + EBlendSoftlight, + EBlendDifference, + EBlendExclusion, + EBlendHslHue, + EBlendHslSaturation, + EBlendHslColor, + EBlendHslLuminosity, + EBlendAllEquations, + + EBlendCount +}; + +enum TInterlockOrdering { + EioNone, + EioPixelInterlockOrdered, + EioPixelInterlockUnordered, + EioSampleInterlockOrdered, + EioSampleInterlockUnordered, + EioShadingRateInterlockOrdered, + EioShadingRateInterlockUnordered, + + EioCount, +}; + +enum TShaderInterface +{ + // Includes both uniform blocks and buffer blocks + EsiUniform = 0, + EsiInput, + EsiOutput, + EsiNone, + + EsiCount +}; + + +class TQualifier { +public: + static const int layoutNotSet = -1; + + void clear() + { + precision = EpqNone; + invariant = false; + makeTemporary(); + declaredBuiltIn = EbvNone; +#ifndef GLSLANG_WEB + noContraction = false; +#endif + } + + // drop qualifiers that don't belong in a temporary variable + void makeTemporary() + { + semanticName = nullptr; + storage = EvqTemporary; + builtIn = EbvNone; + clearInterstage(); + clearMemory(); + specConstant = false; + nonUniform = false; + clearLayout(); + } + + void clearInterstage() + { + clearInterpolation(); +#ifndef GLSLANG_WEB + patch = false; + sample = false; +#endif + } + + void clearInterpolation() + { + centroid = false; + smooth = false; + flat = false; +#ifndef GLSLANG_WEB + nopersp = false; + explicitInterp = false; + pervertexNV = false; + perPrimitiveNV = false; + perViewNV = false; + perTaskNV = false; +#endif + } + + void clearMemory() + { +#ifndef GLSLANG_WEB + coherent = false; + devicecoherent = false; + queuefamilycoherent = false; + workgroupcoherent = false; + subgroupcoherent = false; + shadercallcoherent = false; + nonprivate = false; + volatil = false; + restrict = false; + readonly = false; + writeonly = false; +#endif + } + + const char* semanticName; + TStorageQualifier storage : 6; + TBuiltInVariable builtIn : 9; + TBuiltInVariable declaredBuiltIn : 9; + static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!"); + TPrecisionQualifier precision : 3; + bool invariant : 1; // require canonical treatment for cross-shader invariance + bool centroid : 1; + bool smooth : 1; + bool flat : 1; + // having a constant_id is not sufficient: expressions have no id, but are still specConstant + bool specConstant : 1; + bool nonUniform : 1; + bool explicitOffset : 1; + +#ifdef GLSLANG_WEB + bool isWriteOnly() const { return false; } + bool isReadOnly() const { return false; } + bool isRestrict() const { return false; } + bool isCoherent() const { return false; } + bool isVolatile() const { return false; } + bool isSample() const { return false; } + bool isMemory() const { return false; } + bool isMemoryQualifierImageAndSSBOOnly() const { return false; } + bool bufferReferenceNeedsVulkanMemoryModel() const { return false; } + bool isInterpolation() const { return flat || smooth; } + bool isExplicitInterpolation() const { return false; } + bool isAuxiliary() const { return centroid; } + bool isPatch() const { return false; } + bool isNoContraction() const { return false; } + void setNoContraction() { } + bool isPervertexNV() const { return false; } +#else + bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects + bool nopersp : 1; + bool explicitInterp : 1; + bool pervertexNV : 1; + bool perPrimitiveNV : 1; + bool perViewNV : 1; + bool perTaskNV : 1; + bool patch : 1; + bool sample : 1; + bool restrict : 1; + bool readonly : 1; + bool writeonly : 1; + bool coherent : 1; + bool volatil : 1; + bool devicecoherent : 1; + bool queuefamilycoherent : 1; + bool workgroupcoherent : 1; + bool subgroupcoherent : 1; + bool shadercallcoherent : 1; + bool nonprivate : 1; + bool isWriteOnly() const { return writeonly; } + bool isReadOnly() const { return readonly; } + bool isRestrict() const { return restrict; } + bool isCoherent() const { return coherent; } + bool isVolatile() const { return volatil; } + bool isSample() const { return sample; } + bool isMemory() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; + } + bool isMemoryQualifierImageAndSSBOOnly() const + { + return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; + } + bool bufferReferenceNeedsVulkanMemoryModel() const + { + // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands + return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate; + } + bool isInterpolation() const + { + return flat || smooth || nopersp || explicitInterp; + } + bool isExplicitInterpolation() const + { + return explicitInterp; + } + bool isAuxiliary() const + { + return centroid || patch || sample || pervertexNV; + } + bool isPatch() const { return patch; } + bool isNoContraction() const { return noContraction; } + void setNoContraction() { noContraction = true; } + bool isPervertexNV() const { return pervertexNV; } +#endif + + bool isPipeInput() const + { + switch (storage) { + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + return true; + default: + return false; + } + } + + bool isPipeOutput() const + { + switch (storage) { + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + bool isParamInput() const + { + switch (storage) { + case EvqIn: + case EvqInOut: + case EvqConstReadOnly: + return true; + default: + return false; + } + } + + bool isParamOutput() const + { + switch (storage) { + case EvqOut: + case EvqInOut: + return true; + default: + return false; + } + } + + bool isUniformOrBuffer() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + return true; + default: + return false; + } + } + + bool isIo() const + { + switch (storage) { + case EvqUniform: + case EvqBuffer: + case EvqVaryingIn: + case EvqFragCoord: + case EvqPointCoord: + case EvqFace: + case EvqVertexId: + case EvqInstanceId: + case EvqPosition: + case EvqPointSize: + case EvqClipVertex: + case EvqVaryingOut: + case EvqFragColor: + case EvqFragDepth: + return true; + default: + return false; + } + } + + // non-built-in symbols that might link between compilation units + bool isLinkable() const + { + switch (storage) { + case EvqGlobal: + case EvqVaryingIn: + case EvqVaryingOut: + case EvqUniform: + case EvqBuffer: + case EvqShared: + return true; + default: + return false; + } + } + +#ifdef GLSLANG_WEB + bool isPerView() const { return false; } + bool isTaskMemory() const { return false; } + bool isArrayedIo(EShLanguage language) const { return false; } +#else + bool isPerPrimitive() const { return perPrimitiveNV; } + bool isPerView() const { return perViewNV; } + bool isTaskMemory() const { return perTaskNV; } + + // True if this type of IO is supposed to be arrayed with extra level for per-vertex data + bool isArrayedIo(EShLanguage language) const + { + switch (language) { + case EShLangGeometry: + return isPipeInput(); + case EShLangTessControl: + return ! patch && (isPipeInput() || isPipeOutput()); + case EShLangTessEvaluation: + return ! patch && isPipeInput(); + case EShLangFragment: + return pervertexNV && isPipeInput(); + case EShLangMeshNV: + return ! perTaskNV && isPipeOutput(); + + default: + return false; + } + } +#endif + + // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield + void clearLayout() // all layout + { + clearUniformLayout(); + +#ifndef GLSLANG_WEB + layoutPushConstant = false; + layoutBufferReference = false; + layoutPassthrough = false; + layoutViewportRelative = false; + // -2048 as the default value indicating layoutSecondaryViewportRelative is not set + layoutSecondaryViewportRelativeOffset = -2048; + layoutShaderRecord = false; + layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; + layoutFormat = ElfNone; +#endif + + clearInterstageLayout(); + + layoutSpecConstantId = layoutSpecConstantIdEnd; + } + void clearInterstageLayout() + { + layoutLocation = layoutLocationEnd; + layoutComponent = layoutComponentEnd; +#ifndef GLSLANG_WEB + layoutIndex = layoutIndexEnd; + clearStreamLayout(); + clearXfbLayout(); +#endif + } + +#ifndef GLSLANG_WEB + void clearStreamLayout() + { + layoutStream = layoutStreamEnd; + } + void clearXfbLayout() + { + layoutXfbBuffer = layoutXfbBufferEnd; + layoutXfbStride = layoutXfbStrideEnd; + layoutXfbOffset = layoutXfbOffsetEnd; + } +#endif + + bool hasNonXfbLayout() const + { + return hasUniformLayout() || + hasAnyLocation() || + hasStream() || + hasFormat() || + isShaderRecord() || + isPushConstant() || + hasBufferReference(); + } + bool hasLayout() const + { + return hasNonXfbLayout() || + hasXfb(); + } + TLayoutMatrix layoutMatrix : 3; + TLayoutPacking layoutPacking : 4; + int layoutOffset; + int layoutAlign; + + unsigned int layoutLocation : 12; + static const unsigned int layoutLocationEnd = 0xFFF; + + unsigned int layoutComponent : 3; + static const unsigned int layoutComponentEnd = 4; + + unsigned int layoutSet : 7; + static const unsigned int layoutSetEnd = 0x3F; + + unsigned int layoutBinding : 16; + static const unsigned int layoutBindingEnd = 0xFFFF; + + unsigned int layoutIndex : 8; + static const unsigned int layoutIndexEnd = 0xFF; + + unsigned int layoutStream : 8; + static const unsigned int layoutStreamEnd = 0xFF; + + unsigned int layoutXfbBuffer : 4; + static const unsigned int layoutXfbBufferEnd = 0xF; + + unsigned int layoutXfbStride : 14; + static const unsigned int layoutXfbStrideEnd = 0x3FFF; + + unsigned int layoutXfbOffset : 13; + static const unsigned int layoutXfbOffsetEnd = 0x1FFF; + + unsigned int layoutAttachment : 8; // for input_attachment_index + static const unsigned int layoutAttachmentEnd = 0XFF; + + unsigned int layoutSpecConstantId : 11; + static const unsigned int layoutSpecConstantIdEnd = 0x7FF; + +#ifndef GLSLANG_WEB + // stored as log2 of the actual alignment value + unsigned int layoutBufferReferenceAlign : 6; + static const unsigned int layoutBufferReferenceAlignEnd = 0x3F; + + TLayoutFormat layoutFormat : 8; + + bool layoutPushConstant; + bool layoutBufferReference; + bool layoutPassthrough; + bool layoutViewportRelative; + int layoutSecondaryViewportRelativeOffset; + bool layoutShaderRecord; +#endif + + bool hasUniformLayout() const + { + return hasMatrix() || + hasPacking() || + hasOffset() || + hasBinding() || + hasSet() || + hasAlign(); + } + void clearUniformLayout() // only uniform specific + { + layoutMatrix = ElmNone; + layoutPacking = ElpNone; + layoutOffset = layoutNotSet; + layoutAlign = layoutNotSet; + + layoutSet = layoutSetEnd; + layoutBinding = layoutBindingEnd; +#ifndef GLSLANG_WEB + layoutAttachment = layoutAttachmentEnd; +#endif + } + + bool hasMatrix() const + { + return layoutMatrix != ElmNone; + } + bool hasPacking() const + { + return layoutPacking != ElpNone; + } + bool hasAlign() const + { + return layoutAlign != layoutNotSet; + } + bool hasAnyLocation() const + { + return hasLocation() || + hasComponent() || + hasIndex(); + } + bool hasLocation() const + { + return layoutLocation != layoutLocationEnd; + } + bool hasSet() const + { + return layoutSet != layoutSetEnd; + } + bool hasBinding() const + { + return layoutBinding != layoutBindingEnd; + } +#ifdef GLSLANG_WEB + bool hasOffset() const { return false; } + bool isNonPerspective() const { return false; } + bool hasIndex() const { return false; } + unsigned getIndex() const { return 0; } + bool hasComponent() const { return false; } + bool hasStream() const { return false; } + bool hasFormat() const { return false; } + bool hasXfb() const { return false; } + bool hasXfbBuffer() const { return false; } + bool hasXfbStride() const { return false; } + bool hasXfbOffset() const { return false; } + bool hasAttachment() const { return false; } + TLayoutFormat getFormat() const { return ElfNone; } + bool isPushConstant() const { return false; } + bool isShaderRecord() const { return false; } + bool hasBufferReference() const { return false; } + bool hasBufferReferenceAlign() const { return false; } + bool isNonUniform() const { return false; } +#else + bool hasOffset() const + { + return layoutOffset != layoutNotSet; + } + bool isNonPerspective() const { return nopersp; } + bool hasIndex() const + { + return layoutIndex != layoutIndexEnd; + } + unsigned getIndex() const { return layoutIndex; } + bool hasComponent() const + { + return layoutComponent != layoutComponentEnd; + } + bool hasStream() const + { + return layoutStream != layoutStreamEnd; + } + bool hasFormat() const + { + return layoutFormat != ElfNone; + } + bool hasXfb() const + { + return hasXfbBuffer() || + hasXfbStride() || + hasXfbOffset(); + } + bool hasXfbBuffer() const + { + return layoutXfbBuffer != layoutXfbBufferEnd; + } + bool hasXfbStride() const + { + return layoutXfbStride != layoutXfbStrideEnd; + } + bool hasXfbOffset() const + { + return layoutXfbOffset != layoutXfbOffsetEnd; + } + bool hasAttachment() const + { + return layoutAttachment != layoutAttachmentEnd; + } + TLayoutFormat getFormat() const { return layoutFormat; } + bool isPushConstant() const { return layoutPushConstant; } + bool isShaderRecord() const { return layoutShaderRecord; } + bool hasBufferReference() const { return layoutBufferReference; } + bool hasBufferReferenceAlign() const + { + return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd; + } + bool isNonUniform() const + { + return nonUniform; + } +#endif + bool hasSpecConstantId() const + { + // Not the same thing as being a specialization constant, this + // is just whether or not it was declared with an ID. + return layoutSpecConstantId != layoutSpecConstantIdEnd; + } + bool isSpecConstant() const + { + // True if type is a specialization constant, whether or not it + // had a specialization-constant ID, and false if it is not a + // true front-end constant. + return specConstant; + } + bool isFrontEndConstant() const + { + // True if the front-end knows the final constant value. + // This allows front-end constant folding. + return storage == EvqConst && ! specConstant; + } + bool isConstant() const + { + // True if is either kind of constant; specialization or regular. + return isFrontEndConstant() || isSpecConstant(); + } + void makeSpecConstant() + { + storage = EvqConst; + specConstant = true; + } + static const char* getLayoutPackingString(TLayoutPacking packing) + { + switch (packing) { + case ElpStd140: return "std140"; +#ifndef GLSLANG_WEB + case ElpPacked: return "packed"; + case ElpShared: return "shared"; + case ElpStd430: return "std430"; + case ElpScalar: return "scalar"; +#endif + default: return "none"; + } + } + static const char* getLayoutMatrixString(TLayoutMatrix m) + { + switch (m) { + case ElmColumnMajor: return "column_major"; + case ElmRowMajor: return "row_major"; + default: return "none"; + } + } +#ifdef GLSLANG_WEB + static const char* getLayoutFormatString(TLayoutFormat f) { return "none"; } +#else + static const char* getLayoutFormatString(TLayoutFormat f) + { + switch (f) { + case ElfRgba32f: return "rgba32f"; + case ElfRgba16f: return "rgba16f"; + case ElfRg32f: return "rg32f"; + case ElfRg16f: return "rg16f"; + case ElfR11fG11fB10f: return "r11f_g11f_b10f"; + case ElfR32f: return "r32f"; + case ElfR16f: return "r16f"; + case ElfRgba16: return "rgba16"; + case ElfRgb10A2: return "rgb10_a2"; + case ElfRgba8: return "rgba8"; + case ElfRg16: return "rg16"; + case ElfRg8: return "rg8"; + case ElfR16: return "r16"; + case ElfR8: return "r8"; + case ElfRgba16Snorm: return "rgba16_snorm"; + case ElfRgba8Snorm: return "rgba8_snorm"; + case ElfRg16Snorm: return "rg16_snorm"; + case ElfRg8Snorm: return "rg8_snorm"; + case ElfR16Snorm: return "r16_snorm"; + case ElfR8Snorm: return "r8_snorm"; + + case ElfRgba32i: return "rgba32i"; + case ElfRgba16i: return "rgba16i"; + case ElfRgba8i: return "rgba8i"; + case ElfRg32i: return "rg32i"; + case ElfRg16i: return "rg16i"; + case ElfRg8i: return "rg8i"; + case ElfR32i: return "r32i"; + case ElfR16i: return "r16i"; + case ElfR8i: return "r8i"; + + case ElfRgba32ui: return "rgba32ui"; + case ElfRgba16ui: return "rgba16ui"; + case ElfRgba8ui: return "rgba8ui"; + case ElfRg32ui: return "rg32ui"; + case ElfRg16ui: return "rg16ui"; + case ElfRgb10a2ui: return "rgb10_a2ui"; + case ElfRg8ui: return "rg8ui"; + case ElfR32ui: return "r32ui"; + case ElfR16ui: return "r16ui"; + case ElfR8ui: return "r8ui"; + default: return "none"; + } + } + static const char* getLayoutDepthString(TLayoutDepth d) + { + switch (d) { + case EldAny: return "depth_any"; + case EldGreater: return "depth_greater"; + case EldLess: return "depth_less"; + case EldUnchanged: return "depth_unchanged"; + default: return "none"; + } + } + static const char* getBlendEquationString(TBlendEquationShift e) + { + switch (e) { + case EBlendMultiply: return "blend_support_multiply"; + case EBlendScreen: return "blend_support_screen"; + case EBlendOverlay: return "blend_support_overlay"; + case EBlendDarken: return "blend_support_darken"; + case EBlendLighten: return "blend_support_lighten"; + case EBlendColordodge: return "blend_support_colordodge"; + case EBlendColorburn: return "blend_support_colorburn"; + case EBlendHardlight: return "blend_support_hardlight"; + case EBlendSoftlight: return "blend_support_softlight"; + case EBlendDifference: return "blend_support_difference"; + case EBlendExclusion: return "blend_support_exclusion"; + case EBlendHslHue: return "blend_support_hsl_hue"; + case EBlendHslSaturation: return "blend_support_hsl_saturation"; + case EBlendHslColor: return "blend_support_hsl_color"; + case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; + case EBlendAllEquations: return "blend_support_all_equations"; + default: return "unknown"; + } + } + static const char* getGeometryString(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return "points"; + case ElgLines: return "lines"; + case ElgLinesAdjacency: return "lines_adjacency"; + case ElgLineStrip: return "line_strip"; + case ElgTriangles: return "triangles"; + case ElgTrianglesAdjacency: return "triangles_adjacency"; + case ElgTriangleStrip: return "triangle_strip"; + case ElgQuads: return "quads"; + case ElgIsolines: return "isolines"; + default: return "none"; + } + } + static const char* getVertexSpacingString(TVertexSpacing spacing) + { + switch (spacing) { + case EvsEqual: return "equal_spacing"; + case EvsFractionalEven: return "fractional_even_spacing"; + case EvsFractionalOdd: return "fractional_odd_spacing"; + default: return "none"; + } + } + static const char* getVertexOrderString(TVertexOrder order) + { + switch (order) { + case EvoCw: return "cw"; + case EvoCcw: return "ccw"; + default: return "none"; + } + } + static int mapGeometryToSize(TLayoutGeometry geometry) + { + switch (geometry) { + case ElgPoints: return 1; + case ElgLines: return 2; + case ElgLinesAdjacency: return 4; + case ElgTriangles: return 3; + case ElgTrianglesAdjacency: return 6; + default: return 0; + } + } + static const char* getInterlockOrderingString(TInterlockOrdering order) + { + switch (order) { + case EioPixelInterlockOrdered: return "pixel_interlock_ordered"; + case EioPixelInterlockUnordered: return "pixel_interlock_unordered"; + case EioSampleInterlockOrdered: return "sample_interlock_ordered"; + case EioSampleInterlockUnordered: return "sample_interlock_unordered"; + case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered"; + case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered"; + default: return "none"; + } + } +#endif +}; + +// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. +// So, they will not be part of TType, TQualifier, etc. +struct TShaderQualifiers { + TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives + bool pixelCenterInteger; // fragment shader + bool originUpperLeft; // fragment shader + int invocations; + int vertices; // for tessellation "vertices", geometry & mesh "max_vertices" + TVertexSpacing spacing; + TVertexOrder order; + bool pointMode; + int localSize[3]; // compute shader + bool localSizeNotDefault[3]; // compute shader + int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize +#ifndef GLSLANG_WEB + bool earlyFragmentTests; // fragment input + bool postDepthCoverage; // fragment input + TLayoutDepth layoutDepth; + bool blendEquation; // true if any blend equation was specified + int numViews; // multiview extenstions + TInterlockOrdering interlockOrdering; + bool layoutOverrideCoverage; // true if layout override_coverage set + bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set + bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set + int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set + TLayoutDepth getDepth() const { return layoutDepth; } +#else + TLayoutDepth getDepth() const { return EldNone; } +#endif + + void init() + { + geometry = ElgNone; + originUpperLeft = false; + pixelCenterInteger = false; + invocations = TQualifier::layoutNotSet; + vertices = TQualifier::layoutNotSet; + spacing = EvsNone; + order = EvoNone; + pointMode = false; + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + earlyFragmentTests = false; + postDepthCoverage = false; + layoutDepth = EldNone; + blendEquation = false; + numViews = TQualifier::layoutNotSet; + layoutOverrideCoverage = false; + layoutDerivativeGroupQuads = false; + layoutDerivativeGroupLinear = false; + primitives = TQualifier::layoutNotSet; + interlockOrdering = EioNone; +#endif + } + +#ifdef GLSLANG_WEB + bool hasBlendEquation() const { return false; } +#else + bool hasBlendEquation() const { return blendEquation; } +#endif + + // Merge in characteristics from the 'src' qualifier. They can override when + // set, but never erase when not set. + void merge(const TShaderQualifiers& src) + { + if (src.geometry != ElgNone) + geometry = src.geometry; + if (src.pixelCenterInteger) + pixelCenterInteger = src.pixelCenterInteger; + if (src.originUpperLeft) + originUpperLeft = src.originUpperLeft; + if (src.invocations != TQualifier::layoutNotSet) + invocations = src.invocations; + if (src.vertices != TQualifier::layoutNotSet) + vertices = src.vertices; + if (src.spacing != EvsNone) + spacing = src.spacing; + if (src.order != EvoNone) + order = src.order; + if (src.pointMode) + pointMode = true; + for (int i = 0; i < 3; ++i) { + if (src.localSize[i] > 1) + localSize[i] = src.localSize[i]; + } + for (int i = 0; i < 3; ++i) { + localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i]; + } + for (int i = 0; i < 3; ++i) { + if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) + localSizeSpecId[i] = src.localSizeSpecId[i]; + } +#ifndef GLSLANG_WEB + if (src.earlyFragmentTests) + earlyFragmentTests = true; + if (src.postDepthCoverage) + postDepthCoverage = true; + if (src.layoutDepth) + layoutDepth = src.layoutDepth; + if (src.blendEquation) + blendEquation = src.blendEquation; + if (src.numViews != TQualifier::layoutNotSet) + numViews = src.numViews; + if (src.layoutOverrideCoverage) + layoutOverrideCoverage = src.layoutOverrideCoverage; + if (src.layoutDerivativeGroupQuads) + layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads; + if (src.layoutDerivativeGroupLinear) + layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear; + if (src.primitives != TQualifier::layoutNotSet) + primitives = src.primitives; + if (src.interlockOrdering != EioNone) + interlockOrdering = src.interlockOrdering; +#endif + } +}; + +// +// TPublicType is just temporarily used while parsing and not quite the same +// information kept per node in TType. Due to the bison stack, it can't have +// types that it thinks have non-trivial constructors. It should +// just be used while recognizing the grammar, not anything else. +// Once enough is known about the situation, the proper information +// moved into a TType, or the parse context, etc. +// +class TPublicType { +public: + TBasicType basicType; + TSampler sampler; + TQualifier qualifier; + TShaderQualifiers shaderQualifiers; + int vectorSize : 4; + int matrixCols : 4; + int matrixRows : 4; + bool coopmat : 1; + TArraySizes* arraySizes; + const TType* userDef; + TSourceLoc loc; + TArraySizes* typeParameters; + +#ifdef GLSLANG_WEB + bool isCoopmat() const { return false; } +#else + bool isCoopmat() const { return coopmat; } +#endif + + void initType(const TSourceLoc& l) + { + basicType = EbtVoid; + vectorSize = 1; + matrixRows = 0; + matrixCols = 0; + arraySizes = nullptr; + userDef = nullptr; + loc = l; + typeParameters = nullptr; + coopmat = false; + } + + void initQualifiers(bool global = false) + { + qualifier.clear(); + if (global) + qualifier.storage = EvqGlobal; + } + + void init(const TSourceLoc& l, bool global = false) + { + initType(l); + sampler.clear(); + initQualifiers(global); + shaderQualifiers.init(); + } + + void setVector(int s) + { + matrixRows = 0; + matrixCols = 0; + vectorSize = s; + } + + void setMatrix(int c, int r) + { + matrixRows = r; + matrixCols = c; + vectorSize = 0; + } + + bool isScalar() const + { + return matrixCols == 0 && vectorSize == 1 && arraySizes == nullptr && userDef == nullptr; + } + + // "Image" is a superset of "Subpass" + bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } + bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } +}; + +// +// Base class for things that have a type. +// +class TType { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + // for "empty" type (no args) or simple scalar/vector/matrix + explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for explicit precision qualifier + TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, + bool isVector = false) : + basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), vector1(isVector && vs == 1), coopmat(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + qualifier.storage = q; + qualifier.precision = p; + assert(p >= EpqNone && p <= EpqHigh); + assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices + } + // for turning a TPublicType into a TType, using a shallow copy + explicit TType(const TPublicType& p) : + basicType(p.basicType), + vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmat(p.coopmat), + arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters) + { + if (basicType == EbtSampler) + sampler = p.sampler; + else + sampler.clear(); + qualifier = p.qualifier; + if (p.userDef) { + if (p.userDef->basicType == EbtReference) { + basicType = EbtReference; + referentType = p.userDef->referentType; + } else { + structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues + } + typeName = NewPoolTString(p.userDef->getTypeName().c_str()); + } + if (p.isCoopmat() && p.typeParameters && p.typeParameters->getNumDims() > 0) { + int numBits = p.typeParameters->getDimSize(0); + if (p.basicType == EbtFloat && numBits == 16) { + basicType = EbtFloat16; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtUint && numBits == 8) { + basicType = EbtUint8; + qualifier.precision = EpqNone; + } else if (p.basicType == EbtInt && numBits == 8) { + basicType = EbtInt8; + qualifier.precision = EpqNone; + } + } + } + // for construction of sampler types + TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : + basicType(EbtSampler), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), + sampler(sampler), typeParameters(nullptr) + { + qualifier.clear(); + qualifier.storage = q; + } + // to efficiently make a dereferenced type + // without ever duplicating the outer structure that will be thrown away + // and using only shallow copy + TType(const TType& type, int derefIndex, bool rowMajor = false) + { + if (type.isArray()) { + shallowCopy(type); + if (type.getArraySizes()->getNumDims() == 1) { + arraySizes = nullptr; + } else { + // want our own copy of the array, so we can edit it + arraySizes = new TArraySizes; + arraySizes->copyDereferenced(*type.arraySizes); + } + } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) { + // do a structure dereference + const TTypeList& memberList = *type.getStruct(); + shallowCopy(*memberList[derefIndex].type); + return; + } else { + // do a vector/matrix dereference + shallowCopy(type); + if (matrixCols > 0) { + // dereference from matrix to vector + if (rowMajor) + vectorSize = matrixCols; + else + vectorSize = matrixRows; + matrixCols = 0; + matrixRows = 0; + if (vectorSize == 1) + vector1 = true; + } else if (isVector()) { + // dereference from vector to scalar + vectorSize = 1; + vector1 = false; + } else if (isCoopMat()) { + coopmat = false; + typeParameters = nullptr; + } + } + } + // for making structures, ... + TType(TTypeList* userDef, const TString& n) : + basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + qualifier.clear(); + typeName = NewPoolTString(n.c_str()); + } + // For interface blocks + TType(TTypeList* userDef, const TString& n, const TQualifier& q) : + basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmat(false), + qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr) + { + sampler.clear(); + typeName = NewPoolTString(n.c_str()); + } + // for block reference (first parameter must be EbtReference) + explicit TType(TBasicType t, const TType &p, const TString& n) : + basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), + arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr) + { + assert(t == EbtReference); + typeName = NewPoolTString(n.c_str()); + qualifier.clear(); + qualifier.storage = p.qualifier.storage; + referentType = p.clone(); + } + virtual ~TType() {} + + // Not for use across pool pops; it will cause multiple instances of TType to point to the same information. + // This only works if that information (like a structure's list of types) does not change and + // the instances are sharing the same pool. + void shallowCopy(const TType& copyOf) + { + basicType = copyOf.basicType; + sampler = copyOf.sampler; + qualifier = copyOf.qualifier; + vectorSize = copyOf.vectorSize; + matrixCols = copyOf.matrixCols; + matrixRows = copyOf.matrixRows; + vector1 = copyOf.vector1; + arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents + fieldName = copyOf.fieldName; + typeName = copyOf.typeName; + if (isStruct()) { + structure = copyOf.structure; + } else { + referentType = copyOf.referentType; + } + typeParameters = copyOf.typeParameters; + coopmat = copyOf.isCoopMat(); + } + + // Make complete copy of the whole type graph rooted at 'copyOf'. + void deepCopy(const TType& copyOf) + { + TMap copied; // to enable copying a type graph as a graph, not a tree + deepCopy(copyOf, copied); + } + + // Recursively make temporary + void makeTemporary() + { + getQualifier().makeTemporary(); + + if (isStruct()) + for (unsigned int i = 0; i < structure->size(); ++i) + (*structure)[i].type->makeTemporary(); + } + + TType* clone() const + { + TType *newType = new TType(); + newType->deepCopy(*this); + + return newType; + } + + void makeVector() { vector1 = true; } + + virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; } + virtual bool hiddenMember() const { return basicType == EbtVoid; } + + virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } + virtual const TString& getTypeName() const + { + assert(typeName); + return *typeName; + } + + virtual const TString& getFieldName() const + { + assert(fieldName); + return *fieldName; + } + TShaderInterface getShaderInterface() const + { + if (basicType != EbtBlock) + return EsiNone; + + switch (qualifier.storage) { + default: + return EsiNone; + case EvqVaryingIn: + return EsiInput; + case EvqVaryingOut: + return EsiOutput; + case EvqUniform: + case EvqBuffer: + return EsiUniform; + } + } + + virtual TBasicType getBasicType() const { return basicType; } + virtual const TSampler& getSampler() const { return sampler; } + virtual TSampler& getSampler() { return sampler; } + + virtual TQualifier& getQualifier() { return qualifier; } + virtual const TQualifier& getQualifier() const { return qualifier; } + + virtual int getVectorSize() const { return vectorSize; } // returns 1 for either scalar or vector of size 1, valid for both + virtual int getMatrixCols() const { return matrixCols; } + virtual int getMatrixRows() const { return matrixRows; } + virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } + virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } + virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } +#ifdef GLSLANG_WEB + bool isArrayOfArrays() const { return false; } +#else + bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } +#endif + virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } + virtual const TArraySizes* getArraySizes() const { return arraySizes; } + virtual TArraySizes* getArraySizes() { return arraySizes; } + virtual TType* getReferentType() const { return referentType; } + virtual const TArraySizes* getTypeParameters() const { return typeParameters; } + virtual TArraySizes* getTypeParameters() { return typeParameters; } + + virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } + virtual bool isScalarOrVec1() const { return isScalar() || vector1; } + virtual bool isVector() const { return vectorSize > 1 || vector1; } + virtual bool isMatrix() const { return matrixCols ? true : false; } + virtual bool isArray() const { return arraySizes != nullptr; } + virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); } + virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); } + virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } + virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } + virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } + virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; } + virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } + virtual bool isIntegerDomain() const + { + switch (basicType) { + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtAtomicUint: + return true; + default: + break; + } + return false; + } + virtual bool isOpaque() const { return basicType == EbtSampler +#ifndef GLSLANG_WEB + || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery +#endif + ; } + virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } + + // "Image" is a superset of "Subpass" + virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } + virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } + virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } + // Check the block-name convention of creating a block without populating it's members: + virtual bool isUnusableName() const { return isStruct() && structure == nullptr; } + virtual bool isParameterized() const { return typeParameters != nullptr; } +#ifdef GLSLANG_WEB + bool isAtomic() const { return false; } + bool isCoopMat() const { return false; } + bool isReference() const { return false; } +#else + bool isAtomic() const { return basicType == EbtAtomicUint; } + bool isCoopMat() const { return coopmat; } + bool isReference() const { return getBasicType() == EbtReference; } +#endif + + // return true if this type contains any subtype which satisfies the given predicate. + template + bool contains(P predicate) const + { + if (predicate(this)) + return true; + + const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; + + return isStruct() && std::any_of(structure->begin(), structure->end(), hasa); + } + + // Recursively checks if the type contains the given basic type + virtual bool containsBasicType(TBasicType checkType) const + { + return contains([checkType](const TType* t) { return t->basicType == checkType; } ); + } + + // Recursively check the structure for any arrays, needed for some error checks + virtual bool containsArray() const + { + return contains([](const TType* t) { return t->isArray(); } ); + } + + // Check the structure for any structures, needed for some error checks + virtual bool containsStructure() const + { + return contains([this](const TType* t) { return t != this && t->isStruct(); } ); + } + + // Recursively check the structure for any unsized arrays, needed for triggering a copyUp(). + virtual bool containsUnsizedArray() const + { + return contains([](const TType* t) { return t->isUnsizedArray(); } ); + } + + virtual bool containsOpaque() const + { + return contains([](const TType* t) { return t->isOpaque(); } ); + } + + // Recursively checks if the type contains a built-in variable + virtual bool containsBuiltIn() const + { + return contains([](const TType* t) { return t->isBuiltIn(); } ); + } + + virtual bool containsNonOpaque() const + { + const auto nonOpaque = [](const TType* t) { + switch (t->basicType) { + case EbtVoid: + case EbtFloat: + case EbtDouble: + case EbtFloat16: + case EbtInt8: + case EbtUint8: + case EbtInt16: + case EbtUint16: + case EbtInt: + case EbtUint: + case EbtInt64: + case EbtUint64: + case EbtBool: + case EbtReference: + return true; + default: + return false; + } + }; + + return contains(nonOpaque); + } + + virtual bool containsSpecializationSize() const + { + return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); + } + +#ifdef GLSLANG_WEB + bool containsDouble() const { return false; } + bool contains16BitFloat() const { return false; } + bool contains64BitInt() const { return false; } + bool contains16BitInt() const { return false; } + bool contains8BitInt() const { return false; } + bool containsCoopMat() const { return false; } + bool containsReference() const { return false; } +#else + bool containsDouble() const + { + return containsBasicType(EbtDouble); + } + bool contains16BitFloat() const + { + return containsBasicType(EbtFloat16); + } + bool contains64BitInt() const + { + return containsBasicType(EbtInt64) || containsBasicType(EbtUint64); + } + bool contains16BitInt() const + { + return containsBasicType(EbtInt16) || containsBasicType(EbtUint16); + } + bool contains8BitInt() const + { + return containsBasicType(EbtInt8) || containsBasicType(EbtUint8); + } + bool containsCoopMat() const + { + return contains([](const TType* t) { return t->coopmat; } ); + } + bool containsReference() const + { + return containsBasicType(EbtReference); + } +#endif + + // Array editing methods. Array descriptors can be shared across + // type instances. This allows all uses of the same array + // to be updated at once. E.g., all nodes can be explicitly sized + // by tracking and correcting one implicit size. Or, all nodes + // can get the explicit size on a redeclaration that gives size. + // + // N.B.: Don't share with the shared symbol tables (symbols are + // marked as isReadOnly(). Such symbols with arrays that will be + // edited need to copyUp() on first use, so that + // A) the edits don't effect the shared symbol table, and + // B) the edits are shared across all users. + void updateArraySizes(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(arraySizes != nullptr); + assert(type.arraySizes != nullptr); + *arraySizes = *type.arraySizes; + } + void copyArraySizes(const TArraySizes& s) + { + // For setting a fresh new set of array sizes, not yet worrying about sharing. + arraySizes = new TArraySizes; + *arraySizes = s; + } + void transferArraySizes(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + arraySizes = s; + } + void clearArraySizes() + { + arraySizes = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyArrayInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (arraySizes == nullptr) + copyArraySizes(*s); + else + arraySizes->addInnerSizes(*s); + } + } + void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); } + + // Recursively make the implicit array size the explicit array size. + // Expicit arrays are compile-time or link-time sized, never run-time sized. + // Sometimes, policy calls for an array to be run-time sized even if it was + // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into + // an explicit array. + void adoptImplicitArraySizes(bool skipNonvariablyIndexed) + { + if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed())) + changeOuterArraySize(getImplicitArraySize()); + // For multi-dim per-view arrays, set unsized inner dimension size to 1 + if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized()) + arraySizes->clearInnerUnsized(); + if (isStruct() && structure->size() > 0) { + int lastMember = (int)structure->size() - 1; + for (int i = 0; i < lastMember; ++i) + (*structure)[i].type->adoptImplicitArraySizes(false); + // implement the "last member of an SSBO" policy + (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer); + } + } + + + void updateTypeParameters(const TType& type) + { + // For when we may already be sharing existing array descriptors, + // keeping the pointers the same, just updating the contents. + assert(typeParameters != nullptr); + assert(type.typeParameters != nullptr); + *typeParameters = *type.typeParameters; + } + void copyTypeParameters(const TArraySizes& s) + { + // For setting a fresh new set of type parameters, not yet worrying about sharing. + typeParameters = new TArraySizes; + *typeParameters = s; + } + void transferTypeParameters(TArraySizes* s) + { + // For setting an already allocated set of sizes that this type can use + // (no copy made). + typeParameters = s; + } + void clearTypeParameters() + { + typeParameters = nullptr; + } + + // Add inner array sizes, to any existing sizes, via copy; the + // sizes passed in can still be reused for other purposes. + void copyTypeParametersInnerSizes(const TArraySizes* s) + { + if (s != nullptr) { + if (typeParameters == nullptr) + copyTypeParameters(*s); + else + typeParameters->addInnerSizes(*s); + } + } + + + + const char* getBasicString() const + { + return TType::getBasicString(basicType); + } + + static const char* getBasicString(TBasicType t) + { + switch (t) { + case EbtFloat: return "float"; + case EbtInt: return "int"; + case EbtUint: return "uint"; + case EbtSampler: return "sampler/image"; +#ifndef GLSLANG_WEB + case EbtVoid: return "void"; + case EbtDouble: return "double"; + case EbtFloat16: return "float16_t"; + case EbtInt8: return "int8_t"; + case EbtUint8: return "uint8_t"; + case EbtInt16: return "int16_t"; + case EbtUint16: return "uint16_t"; + case EbtInt64: return "int64_t"; + case EbtUint64: return "uint64_t"; + case EbtBool: return "bool"; + case EbtAtomicUint: return "atomic_uint"; + case EbtStruct: return "structure"; + case EbtBlock: return "block"; + case EbtAccStruct: return "accelerationStructureNV"; + case EbtRayQuery: return "rayQueryEXT"; + case EbtReference: return "reference"; +#endif + default: return "unknown type"; + } + } + +#ifdef GLSLANG_WEB + TString getCompleteString() const { return ""; } + const char* getStorageQualifierString() const { return ""; } + const char* getBuiltInVariableString() const { return ""; } + const char* getPrecisionQualifierString() const { return ""; } + TString getBasicTypeString() const { return ""; } +#else + TString getCompleteString() const + { + TString typeString; + + const auto appendStr = [&](const char* s) { typeString.append(s); }; + const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; + const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; + + if (qualifier.hasLayout()) { + // To reduce noise, skip this if the only layout is an xfb_buffer + // with no triggering xfb_offset. + TQualifier noXfbBuffer = qualifier; + noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; + if (noXfbBuffer.hasLayout()) { + appendStr("layout("); + if (qualifier.hasAnyLocation()) { + appendStr(" location="); + appendUint(qualifier.layoutLocation); + if (qualifier.hasComponent()) { + appendStr(" component="); + appendUint(qualifier.layoutComponent); + } + if (qualifier.hasIndex()) { + appendStr(" index="); + appendUint(qualifier.layoutIndex); + } + } + if (qualifier.hasSet()) { + appendStr(" set="); + appendUint(qualifier.layoutSet); + } + if (qualifier.hasBinding()) { + appendStr(" binding="); + appendUint(qualifier.layoutBinding); + } + if (qualifier.hasStream()) { + appendStr(" stream="); + appendUint(qualifier.layoutStream); + } + if (qualifier.hasMatrix()) { + appendStr(" "); + appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); + } + if (qualifier.hasPacking()) { + appendStr(" "); + appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking)); + } + if (qualifier.hasOffset()) { + appendStr(" offset="); + appendInt(qualifier.layoutOffset); + } + if (qualifier.hasAlign()) { + appendStr(" align="); + appendInt(qualifier.layoutAlign); + } + if (qualifier.hasFormat()) { + appendStr(" "); + appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat)); + } + if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) { + appendStr(" xfb_buffer="); + appendUint(qualifier.layoutXfbBuffer); + } + if (qualifier.hasXfbOffset()) { + appendStr(" xfb_offset="); + appendUint(qualifier.layoutXfbOffset); + } + if (qualifier.hasXfbStride()) { + appendStr(" xfb_stride="); + appendUint(qualifier.layoutXfbStride); + } + if (qualifier.hasAttachment()) { + appendStr(" input_attachment_index="); + appendUint(qualifier.layoutAttachment); + } + if (qualifier.hasSpecConstantId()) { + appendStr(" constant_id="); + appendUint(qualifier.layoutSpecConstantId); + } + if (qualifier.layoutPushConstant) + appendStr(" push_constant"); + if (qualifier.layoutBufferReference) + appendStr(" buffer_reference"); + if (qualifier.hasBufferReferenceAlign()) { + appendStr(" buffer_reference_align="); + appendUint(1u << qualifier.layoutBufferReferenceAlign); + } + + if (qualifier.layoutPassthrough) + appendStr(" passthrough"); + if (qualifier.layoutViewportRelative) + appendStr(" layoutViewportRelative"); + if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { + appendStr(" layoutSecondaryViewportRelativeOffset="); + appendInt(qualifier.layoutSecondaryViewportRelativeOffset); + } + if (qualifier.layoutShaderRecord) + appendStr(" shaderRecordNV"); + + appendStr(")"); + } + } + + if (qualifier.invariant) + appendStr(" invariant"); + if (qualifier.noContraction) + appendStr(" noContraction"); + if (qualifier.centroid) + appendStr(" centroid"); + if (qualifier.smooth) + appendStr(" smooth"); + if (qualifier.flat) + appendStr(" flat"); + if (qualifier.nopersp) + appendStr(" noperspective"); + if (qualifier.explicitInterp) + appendStr(" __explicitInterpAMD"); + if (qualifier.pervertexNV) + appendStr(" pervertexNV"); + if (qualifier.perPrimitiveNV) + appendStr(" perprimitiveNV"); + if (qualifier.perViewNV) + appendStr(" perviewNV"); + if (qualifier.perTaskNV) + appendStr(" taskNV"); + if (qualifier.patch) + appendStr(" patch"); + if (qualifier.sample) + appendStr(" sample"); + if (qualifier.coherent) + appendStr(" coherent"); + if (qualifier.devicecoherent) + appendStr(" devicecoherent"); + if (qualifier.queuefamilycoherent) + appendStr(" queuefamilycoherent"); + if (qualifier.workgroupcoherent) + appendStr(" workgroupcoherent"); + if (qualifier.subgroupcoherent) + appendStr(" subgroupcoherent"); + if (qualifier.shadercallcoherent) + appendStr(" shadercallcoherent"); + if (qualifier.nonprivate) + appendStr(" nonprivate"); + if (qualifier.volatil) + appendStr(" volatile"); + if (qualifier.restrict) + appendStr(" restrict"); + if (qualifier.readonly) + appendStr(" readonly"); + if (qualifier.writeonly) + appendStr(" writeonly"); + if (qualifier.specConstant) + appendStr(" specialization-constant"); + if (qualifier.nonUniform) + appendStr(" nonuniform"); + appendStr(" "); + appendStr(getStorageQualifierString()); + if (isArray()) { + for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { + int size = arraySizes->getDimSize(i); + if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) + appendStr(" runtime-sized array of"); + else { + if (size == UnsizedArraySize) { + appendStr(" unsized"); + if (i == 0) { + appendStr(" "); + appendInt(arraySizes->getImplicitSize()); + } + } else { + appendStr(" "); + appendInt(arraySizes->getDimSize(i)); + } + appendStr("-element array of"); + } + } + } + if (isParameterized()) { + appendStr("<"); + for(int i = 0; i < (int)typeParameters->getNumDims(); ++i) { + appendInt(typeParameters->getDimSize(i)); + if (i != (int)typeParameters->getNumDims() - 1) + appendStr(", "); + } + appendStr(">"); + } + if (qualifier.precision != EpqNone) { + appendStr(" "); + appendStr(getPrecisionQualifierString()); + } + if (isMatrix()) { + appendStr(" "); + appendInt(matrixCols); + appendStr("X"); + appendInt(matrixRows); + appendStr(" matrix of"); + } else if (isVector()) { + appendStr(" "); + appendInt(vectorSize); + appendStr("-component vector of"); + } + + appendStr(" "); + typeString.append(getBasicTypeString()); + + if (qualifier.builtIn != EbvNone) { + appendStr(" "); + appendStr(getBuiltInVariableString()); + } + + // Add struct/block members + if (isStruct() && structure) { + appendStr("{"); + bool hasHiddenMember = true; + for (size_t i = 0; i < structure->size(); ++i) { + if (! (*structure)[i].type->hiddenMember()) { + if (!hasHiddenMember) + appendStr(", "); + typeString.append((*structure)[i].type->getCompleteString()); + typeString.append(" "); + typeString.append((*structure)[i].type->getFieldName()); + hasHiddenMember = false; + } + } + appendStr("}"); + } + + return typeString; + } + + TString getBasicTypeString() const + { + if (basicType == EbtSampler) + return sampler.getString(); + else + return getBasicString(); + } + + const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } + const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } + const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } +#endif + + const TTypeList* getStruct() const { assert(isStruct()); return structure; } + void setStruct(TTypeList* s) { assert(isStruct()); structure = s; } + TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads + void setBasicType(const TBasicType& t) { basicType = t; } + + int computeNumComponents() const + { + int components = 0; + + if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { + for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) + components += ((*tl).type)->computeNumComponents(); + } else if (matrixCols) + components = matrixCols * matrixRows; + else + components = vectorSize; + + if (arraySizes != nullptr) { + components *= arraySizes->getCumulativeSize(); + } + + return components; + } + + // append this type's mangled name to the passed in 'name' + void appendMangledName(TString& name) const + { + buildMangledName(name); + name += ';' ; + } + + // Do two structure types match? They could be declared independently, + // in different places, but still might satisfy the definition of matching. + // From the spec: + // + // "Structures must have the same name, sequence of type names, and + // type definitions, and member names to be considered the same type. + // This rule applies recursively for nested or embedded types." + // + bool sameStructType(const TType& right) const + { + // Most commonly, they are both nullptr, or the same pointer to the same actual structure + if ((!isStruct() && !right.isStruct()) || + (isStruct() && right.isStruct() && structure == right.structure)) + return true; + + // Both being nullptr was caught above, now they both have to be structures of the same number of elements + if (!isStruct() || !right.isStruct() || + structure->size() != right.structure->size()) + return false; + + // Structure names have to match + if (*typeName != *right.typeName) + return false; + + // Compare the names and types of all the members, which have to match + for (unsigned int i = 0; i < structure->size(); ++i) { + if ((*structure)[i].type->getFieldName() != (*right.structure)[i].type->getFieldName()) + return false; + + if (*(*structure)[i].type != *(*right.structure)[i].type) + return false; + } + + return true; + } + + bool sameReferenceType(const TType& right) const + { + if (isReference() != right.isReference()) + return false; + + if (!isReference() && !right.isReference()) + return true; + + assert(referentType != nullptr); + assert(right.referentType != nullptr); + + if (referentType == right.referentType) + return true; + + return *referentType == *right.referentType; + } + + // See if two types match, in all aspects except arrayness + bool sameElementType(const TType& right) const + { + return basicType == right.basicType && sameElementShape(right); + } + + // See if two type's arrayness match + bool sameArrayness(const TType& right) const + { + return ((arraySizes == nullptr && right.arraySizes == nullptr) || + (arraySizes != nullptr && right.arraySizes != nullptr && *arraySizes == *right.arraySizes)); + } + + // See if two type's arrayness match in everything except their outer dimension + bool sameInnerArrayness(const TType& right) const + { + assert(arraySizes != nullptr && right.arraySizes != nullptr); + return arraySizes->sameInnerArrayness(*right.arraySizes); + } + + // See if two type's parameters match + bool sameTypeParameters(const TType& right) const + { + return ((typeParameters == nullptr && right.typeParameters == nullptr) || + (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters)); + } + + // See if two type's elements match in all ways except basic type + bool sameElementShape(const TType& right) const + { + return sampler == right.sampler && + vectorSize == right.vectorSize && + matrixCols == right.matrixCols && + matrixRows == right.matrixRows && + vector1 == right.vector1 && + isCoopMat() == right.isCoopMat() && + sameStructType(right) && + sameReferenceType(right); + } + + // See if a cooperative matrix type parameter with unspecified parameters is + // an OK function parameter + bool coopMatParameterOK(const TType& right) const + { + return isCoopMat() && right.isCoopMat() && (getBasicType() == right.getBasicType()) && + typeParameters == nullptr && right.typeParameters != nullptr; + } + + bool sameCoopMatBaseType(const TType &right) const { + bool rv = coopmat && right.coopmat; + if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16) + rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16; + else if (getBasicType() == EbtUint || getBasicType() == EbtUint8) + rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8; + else if (getBasicType() == EbtInt || getBasicType() == EbtInt8) + rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8; + else + rv = false; + return rv; + } + + + // See if two types match in all ways (just the actual type, not qualification) + bool operator==(const TType& right) const + { + return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right); + } + + bool operator!=(const TType& right) const + { + return ! operator==(right); + } + + unsigned int getBufferReferenceAlignment() const + { +#ifndef GLSLANG_WEB + if (getBasicType() == glslang::EbtReference) { + return getReferentType()->getQualifier().hasBufferReferenceAlign() ? + (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u; + } +#endif + return 0; + } + +protected: + // Require consumer to pick between deep copy and shallow copy. + TType(const TType& type); + TType& operator=(const TType& type); + + // Recursively copy a type graph, while preserving the graph-like + // quality. That is, don't make more than one copy of a structure that + // gets reused multiple times in the type graph. + void deepCopy(const TType& copyOf, TMap& copiedMap) + { + shallowCopy(copyOf); + + if (copyOf.arraySizes) { + arraySizes = new TArraySizes; + *arraySizes = *copyOf.arraySizes; + } + + if (copyOf.typeParameters) { + typeParameters = new TArraySizes; + *typeParameters = *copyOf.typeParameters; + } + + if (copyOf.isStruct() && copyOf.structure) { + auto prevCopy = copiedMap.find(copyOf.structure); + if (prevCopy != copiedMap.end()) + structure = prevCopy->second; + else { + structure = new TTypeList; + copiedMap[copyOf.structure] = structure; + for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { + TTypeLoc typeLoc; + typeLoc.loc = (*copyOf.structure)[i].loc; + typeLoc.type = new TType(); + typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap); + structure->push_back(typeLoc); + } + } + } + + if (copyOf.fieldName) + fieldName = NewPoolTString(copyOf.fieldName->c_str()); + if (copyOf.typeName) + typeName = NewPoolTString(copyOf.typeName->c_str()); + } + + + void buildMangledName(TString&) const; + + TBasicType basicType : 8; + int vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. + int matrixCols : 4; + int matrixRows : 4; + bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. + // GLSL 4.5 never has a 1-component vector; so this will always be false until such + // functionality is added. + // HLSL does have a 1-component vectors, so this will be true to disambiguate + // from a scalar. + bool coopmat : 1; + TQualifier qualifier; + + TArraySizes* arraySizes; // nullptr unless an array; can be shared across types + // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so + // conserve space by making these a union + union { + TTypeList* structure; // invalid unless this is a struct; can be shared across types + TType *referentType; // invalid unless this is an EbtReference + }; + TString *fieldName; // for structure field names + TString *typeName; // for structure type name + TSampler sampler; + TArraySizes* typeParameters;// nullptr unless a parameterized type; can be shared across types +}; + +} // end namespace glslang + +#endif // _TYPES_INCLUDED_ diff --git a/ios/include/glslang/Include/arrays.h b/ios/include/glslang/Include/arrays.h new file mode 100644 index 00000000..7f047d9f --- /dev/null +++ b/ios/include/glslang/Include/arrays.h @@ -0,0 +1,341 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 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. +// + +// +// Implement types for tracking GLSL arrays, arrays of arrays, etc. +// + +#ifndef _ARRAYS_INCLUDED +#define _ARRAYS_INCLUDED + +#include + +namespace glslang { + +// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else. +const int UnsizedArraySize = 0; + +class TIntermTyped; +extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*); + +// Specialization constants need both a nominal size and a node that defines +// the specialization constant being used. Array types are the same when their +// size and specialization constant nodes are the same. +struct TArraySize { + unsigned int size; + TIntermTyped* node; // nullptr means no specialization constant node + bool operator==(const TArraySize& rhs) const + { + if (size != rhs.size) + return false; + if (node == nullptr || rhs.node == nullptr) + return node == rhs.node; + + return SameSpecializationConstants(node, rhs.node); + } +}; + +// +// TSmallArrayVector is used as the container for the set of sizes in TArraySizes. +// It has generic-container semantics, while TArraySizes has array-of-array semantics. +// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy. +// +struct TSmallArrayVector { + // + // TODO: memory: TSmallArrayVector is intended to be smaller. + // Almost all arrays could be handled by two sizes each fitting + // in 16 bits, needing a real vector only in the cases where there + // are more than 3 sizes or a size needing more than 16 bits. + // + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TSmallArrayVector() : sizes(nullptr) { } + virtual ~TSmallArrayVector() { dealloc(); } + + // For breaking into two non-shared copies, independently modifiable. + TSmallArrayVector& operator=(const TSmallArrayVector& from) + { + if (from.sizes == nullptr) + sizes = nullptr; + else { + alloc(); + *sizes = *from.sizes; + } + + return *this; + } + + int size() const + { + if (sizes == nullptr) + return 0; + return (int)sizes->size(); + } + + unsigned int frontSize() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().size; + } + + TIntermTyped* frontNode() const + { + assert(sizes != nullptr && sizes->size() > 0); + return sizes->front().node; + } + + void changeFront(unsigned int s) + { + assert(sizes != nullptr); + // this should only happen for implicitly sized arrays, not specialization constants + assert(sizes->front().node == nullptr); + sizes->front().size = s; + } + + void push_back(unsigned int e, TIntermTyped* n) + { + alloc(); + TArraySize pair = { e, n }; + sizes->push_back(pair); + } + + void push_back(const TSmallArrayVector& newDims) + { + alloc(); + sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end()); + } + + void pop_front() + { + assert(sizes != nullptr && sizes->size() > 0); + if (sizes->size() == 1) + dealloc(); + else + sizes->erase(sizes->begin()); + } + + // 'this' should currently not be holding anything, and copyNonFront + // will make it hold a copy of all but the first element of rhs. + // (This would be useful for making a type that is dereferenced by + // one dimension.) + void copyNonFront(const TSmallArrayVector& rhs) + { + assert(sizes == nullptr); + if (rhs.size() > 1) { + alloc(); + sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end()); + } + } + + unsigned int getDimSize(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].size; + } + + void setDimSize(int i, unsigned int size) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + assert((*sizes)[i].node == nullptr); + (*sizes)[i].size = size; + } + + TIntermTyped* getDimNode(int i) const + { + assert(sizes != nullptr && (int)sizes->size() > i); + return (*sizes)[i].node; + } + + bool operator==(const TSmallArrayVector& rhs) const + { + if (sizes == nullptr && rhs.sizes == nullptr) + return true; + if (sizes == nullptr || rhs.sizes == nullptr) + return false; + return *sizes == *rhs.sizes; + } + bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); } + +protected: + TSmallArrayVector(const TSmallArrayVector&); + + void alloc() + { + if (sizes == nullptr) + sizes = new TVector; + } + void dealloc() + { + delete sizes; + sizes = nullptr; + } + + TVector* sizes; // will either hold such a pointer, or in the future, hold the two array sizes +}; + +// +// Represent an array, or array of arrays, to arbitrary depth. This is not +// done through a hierarchy of types in a type tree, rather all contiguous arrayness +// in the type hierarchy is localized into this single cumulative object. +// +// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero +// for the vast majority of types that are non-array types. +// +// Order Policy: these are all identical: +// - left to right order within a contiguous set of ...[..][..][..]... in the source language +// - index order 0, 1, 2, ... within the 'sizes' member below +// - outer-most to inner-most +// +struct TArraySizes { + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + + TArraySizes() : implicitArraySize(1), variablyIndexed(false) { } + + // For breaking into two non-shared copies, independently modifiable. + TArraySizes& operator=(const TArraySizes& from) + { + implicitArraySize = from.implicitArraySize; + variablyIndexed = from.variablyIndexed; + sizes = from.sizes; + + return *this; + } + + // translate from array-of-array semantics to container semantics + int getNumDims() const { return sizes.size(); } + int getDimSize(int dim) const { return sizes.getDimSize(dim); } + TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); } + void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); } + int getOuterSize() const { return sizes.frontSize(); } + TIntermTyped* getOuterNode() const { return sizes.frontNode(); } + int getCumulativeSize() const + { + int size = 1; + for (int d = 0; d < sizes.size(); ++d) { + // this only makes sense in paths that have a known array size + assert(sizes.getDimSize(d) != UnsizedArraySize); + size *= sizes.getDimSize(d); + } + return size; + } + void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); } + void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); } + void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); } + void addInnerSize(TArraySize pair) { + sizes.push_back(pair.size, pair.node); + } + void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); } + void changeOuterSize(int s) { sizes.changeFront((unsigned)s); } + int getImplicitSize() const { return implicitArraySize; } + void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); } + bool isInnerUnsized() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + return true; + } + + return false; + } + bool clearInnerUnsized() + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) + setDimSize(d, 1); + } + + return false; + } + bool isInnerSpecialization() const + { + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimNode(d) != nullptr) + return true; + } + + return false; + } + bool isOuterSpecialization() + { + return sizes.getDimNode(0) != nullptr; + } + + bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); } + bool isSized() const { return getOuterSize() != UnsizedArraySize; } + void dereference() { sizes.pop_front(); } + void copyDereferenced(const TArraySizes& rhs) + { + assert(sizes.size() == 0); + if (rhs.sizes.size() > 1) + sizes.copyNonFront(rhs.sizes); + } + + bool sameInnerArrayness(const TArraySizes& rhs) const + { + if (sizes.size() != rhs.sizes.size()) + return false; + + for (int d = 1; d < sizes.size(); ++d) { + if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) || + sizes.getDimNode(d) != rhs.sizes.getDimNode(d)) + return false; + } + + return true; + } + + void setVariablyIndexed() { variablyIndexed = true; } + bool isVariablyIndexed() const { return variablyIndexed; } + + bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; } + bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; } + +protected: + TSmallArrayVector sizes; + + TArraySizes(const TArraySizes&); + + // For tracking maximum referenced compile-time constant index. + // Applies only to the outer-most dimension. Potentially becomes + // the implicit size of the array, if not variably indexed and + // otherwise legal. + int implicitArraySize; + bool variablyIndexed; // true if array is indexed with a non compile-time constant +}; + +} // end namespace glslang + +#endif // _ARRAYS_INCLUDED_ diff --git a/ios/include/glslang/Include/glslang_c_interface.h b/ios/include/glslang/Include/glslang_c_interface.h new file mode 100644 index 00000000..5a450e0e --- /dev/null +++ b/ios/include/glslang/Include/glslang_c_interface.h @@ -0,0 +1,232 @@ +/** + 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. +**/ + +#ifndef GLSLANG_C_IFACE_H_INCLUDED +#define GLSLANG_C_IFACE_H_INCLUDED + +#include +#include + +#include "glslang_c_shader_types.h" + +typedef struct glslang_shader_s glslang_shader_t; +typedef struct glslang_program_s glslang_program_t; + +/* TLimits counterpart */ +typedef struct glslang_limits_s { + bool non_inductive_for_loops; + bool while_loops; + bool do_while_loops; + bool general_uniform_indexing; + bool general_attribute_matrix_vector_indexing; + bool general_varying_indexing; + bool general_sampler_indexing; + bool general_variable_indexing; + bool general_constant_matrix_vector_indexing; +} glslang_limits_t; + +/* TBuiltInResource counterpart */ +typedef struct glslang_resource_s { + int max_lights; + int max_clip_planes; + int max_texture_units; + int max_texture_coords; + int max_vertex_attribs; + int max_vertex_uniform_components; + int max_varying_floats; + int max_vertex_texture_image_units; + int max_combined_texture_image_units; + int max_texture_image_units; + int max_fragment_uniform_components; + int max_draw_buffers; + int max_vertex_uniform_vectors; + int max_varying_vectors; + int max_fragment_uniform_vectors; + int max_vertex_output_vectors; + int max_fragment_input_vectors; + int min_program_texel_offset; + int max_program_texel_offset; + int max_clip_distances; + int max_compute_work_group_count_x; + int max_compute_work_group_count_y; + int max_compute_work_group_count_z; + int max_compute_work_group_size_x; + int max_compute_work_group_size_y; + int max_compute_work_group_size_z; + int max_compute_uniform_components; + int max_compute_texture_image_units; + int max_compute_image_uniforms; + int max_compute_atomic_counters; + int max_compute_atomic_counter_buffers; + int max_varying_components; + int max_vertex_output_components; + int max_geometry_input_components; + int max_geometry_output_components; + int max_fragment_input_components; + int max_image_units; + int max_combined_image_units_and_fragment_outputs; + int max_combined_shader_output_resources; + int max_image_samples; + int max_vertex_image_uniforms; + int max_tess_control_image_uniforms; + int max_tess_evaluation_image_uniforms; + int max_geometry_image_uniforms; + int max_fragment_image_uniforms; + int max_combined_image_uniforms; + int max_geometry_texture_image_units; + int max_geometry_output_vertices; + int max_geometry_total_output_components; + int max_geometry_uniform_components; + int max_geometry_varying_components; + int max_tess_control_input_components; + int max_tess_control_output_components; + int max_tess_control_texture_image_units; + int max_tess_control_uniform_components; + int max_tess_control_total_output_components; + int max_tess_evaluation_input_components; + int max_tess_evaluation_output_components; + int max_tess_evaluation_texture_image_units; + int max_tess_evaluation_uniform_components; + int max_tess_patch_components; + int max_patch_vertices; + int max_tess_gen_level; + int max_viewports; + int max_vertex_atomic_counters; + int max_tess_control_atomic_counters; + int max_tess_evaluation_atomic_counters; + int max_geometry_atomic_counters; + int max_fragment_atomic_counters; + int max_combined_atomic_counters; + int max_atomic_counter_bindings; + int max_vertex_atomic_counter_buffers; + int max_tess_control_atomic_counter_buffers; + int max_tess_evaluation_atomic_counter_buffers; + int max_geometry_atomic_counter_buffers; + int max_fragment_atomic_counter_buffers; + int max_combined_atomic_counter_buffers; + int max_atomic_counter_buffer_size; + int max_transform_feedback_buffers; + int max_transform_feedback_interleaved_components; + int max_cull_distances; + int max_combined_clip_and_cull_distances; + int max_samples; + int max_mesh_output_vertices_nv; + int max_mesh_output_primitives_nv; + int max_mesh_work_group_size_x_nv; + int max_mesh_work_group_size_y_nv; + int max_mesh_work_group_size_z_nv; + int max_task_work_group_size_x_nv; + int max_task_work_group_size_y_nv; + int max_task_work_group_size_z_nv; + int max_mesh_view_count_nv; + + glslang_limits_t limits; +} glslang_resource_t; + +typedef struct glslang_input_s { + glslang_source_t language; + glslang_stage_t stage; + glslang_client_t client; + glslang_target_client_version_t client_version; + glslang_target_language_t target_language; + glslang_target_language_version_t target_language_version; + /** Shader source code */ + const char* code; + int default_version; + glslang_profile_t default_profile; + int force_default_version_and_profile; + int forward_compatible; + glslang_messages_t messages; + const glslang_resource_t* resource; +} glslang_input_t; + +/* Inclusion result structure allocated by C include_local/include_system callbacks */ +typedef struct glsl_include_result_s { + /* Header file name or NULL if inclusion failed */ + const char* header_name; + + /* Header contents or NULL */ + const char* header_data; + size_t header_length; + +} glsl_include_result_t; + +/* Callback for local file inclusion */ +typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name, + size_t include_depth); + +/* Callback for system file inclusion */ +typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name, + const char* includer_name, size_t include_depth); + +/* Callback for include result destruction */ +typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result); + +/* Collection of callbacks for GLSL preprocessor */ +typedef struct glsl_include_callbacks_s { + glsl_include_system_func include_system; + glsl_include_local_func include_local; + glsl_free_include_result_func free_include_result; +} glsl_include_callbacks_t; + +#ifdef __cplusplus +extern "C" { +#endif + +int glslang_initialize_process(); +void glslang_finalize_process(); + +glslang_shader_t* glslang_shader_create(const glslang_input_t* input); +void glslang_shader_delete(glslang_shader_t* shader); +int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input); +int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input); +const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader); +const char* glslang_shader_get_info_log(glslang_shader_t* shader); +const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader); + +glslang_program_t* glslang_program_create(); +void glslang_program_delete(glslang_program_t* program); +void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader); +int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t +void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage); +size_t glslang_program_SPIRV_get_size(glslang_program_t* program); +void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*); +unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program); +const char* glslang_program_SPIRV_get_messages(glslang_program_t* program); +const char* glslang_program_get_info_log(glslang_program_t* program); +const char* glslang_program_get_info_debug_log(glslang_program_t* program); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */ diff --git a/ios/include/glslang/Include/glslang_c_shader_types.h b/ios/include/glslang/Include/glslang_c_shader_types.h new file mode 100644 index 00000000..769f4c4a --- /dev/null +++ b/ios/include/glslang/Include/glslang_c_shader_types.h @@ -0,0 +1,182 @@ +/** + 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. +**/ + +#ifndef C_SHADER_TYPES_H_INCLUDED +#define C_SHADER_TYPES_H_INCLUDED + +#define LAST_ELEMENT_MARKER(x) x + +/* EShLanguage counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX, + GLSLANG_STAGE_TESSCONTROL, + GLSLANG_STAGE_TESSEVALUATION, + GLSLANG_STAGE_GEOMETRY, + GLSLANG_STAGE_FRAGMENT, + GLSLANG_STAGE_COMPUTE, + GLSLANG_STAGE_RAYGEN_NV, + GLSLANG_STAGE_INTERSECT_NV, + GLSLANG_STAGE_ANYHIT_NV, + GLSLANG_STAGE_CLOSESTHIT_NV, + GLSLANG_STAGE_MISS_NV, + GLSLANG_STAGE_CALLABLE_NV, + GLSLANG_STAGE_TASK_NV, + GLSLANG_STAGE_MESH_NV, + LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT), +} glslang_stage_t; // would be better as stage, but this is ancient now + +/* EShLanguageMask counterpart */ +typedef enum { + GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX), + GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL), + GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION), + GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY), + GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT), + GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE), + GLSLANG_STAGE_RAYGEN_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV), + GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV), + GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV), + GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV), + GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV), + GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV), + GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV), + GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV), + LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT), +} glslang_stage_mask_t; + +/* EShSource counterpart */ +typedef enum { + GLSLANG_SOURCE_NONE, + GLSLANG_SOURCE_GLSL, + GLSLANG_SOURCE_HLSL, + LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT), +} glslang_source_t; + +/* EShClient counterpart */ +typedef enum { + GLSLANG_CLIENT_NONE, + GLSLANG_CLIENT_VULKAN, + GLSLANG_CLIENT_OPENGL, + LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT), +} glslang_client_t; + +/* EShTargetLanguage counterpart */ +typedef enum { + GLSLANG_TARGET_NONE, + GLSLANG_TARGET_SPV, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT), +} glslang_target_language_t; + +/* SH_TARGET_ClientVersion counterpart */ +typedef enum { + GLSLANG_TARGET_VULKAN_1_0 = (1 << 22), + GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12), + GLSLANG_TARGET_OPENGL_450 = 450, + LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT), +} glslang_target_client_version_t; + +/* SH_TARGET_LanguageVersion counterpart */ +typedef enum { + GLSLANG_TARGET_SPV_1_0 = (1 << 16), + GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8), + GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8), + GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8), + GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8), + GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8), + LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT), +} glslang_target_language_version_t; + +/* EShExecutable counterpart */ +typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t; + +/* EShOptimizationLevel counterpart */ +typedef enum { + GLSLANG_OPT_NO_GENERATION, + GLSLANG_OPT_NONE, + GLSLANG_OPT_SIMPLE, + GLSLANG_OPT_FULL, + LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT), +} glslang_optimization_level_t; + +/* EShTextureSamplerTransformMode counterpart */ +typedef enum { + GLSLANG_TEX_SAMP_TRANS_KEEP, + GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER, + LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT), +} glslang_texture_sampler_transform_mode_t; + +/* EShMessages counterpart */ +typedef enum { + GLSLANG_MSG_DEFAULT_BIT = 0, + GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0), + GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1), + GLSLANG_MSG_AST_BIT = (1 << 2), + GLSLANG_MSG_SPV_RULES_BIT = (1 << 3), + GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4), + GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5), + GLSLANG_MSG_READ_HLSL_BIT = (1 << 6), + GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7), + GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8), + GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9), + GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10), + GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11), + GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12), + GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13), + GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14), + LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT), +} glslang_messages_t; + +/* EShReflectionOptions counterpart */ +typedef enum { + GLSLANG_REFLECTION_DEFAULT_BIT = 0, + GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0), + GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1), + GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2), + GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3), + GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4), + GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5), + LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT), +} glslang_reflection_options_t; + +/* EProfile counterpart (from Versions.h) */ +typedef enum { + GLSLANG_BAD_PROFILE = 0, + GLSLANG_NO_PROFILE = (1 << 0), + GLSLANG_CORE_PROFILE = (1 << 1), + GLSLANG_COMPATIBILITY_PROFILE = (1 << 2), + GLSLANG_ES_PROFILE = (1 << 3), + LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT), +} glslang_profile_t; + +#undef LAST_ELEMENT_MARKER + +#endif diff --git a/ios/include/glslang/Include/intermediate.h b/ios/include/glslang/Include/intermediate.h new file mode 100644 index 00000000..bf12fcf8 --- /dev/null +++ b/ios/include/glslang/Include/intermediate.h @@ -0,0 +1,1805 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2016 LunarG, 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. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef __INTERMEDIATE_H +#define __INTERMEDIATE_H + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' + #pragma warning(disable : 5026) // 'glslang::TIntermUnary': move constructor was implicitly defined as deleted +#endif + +#include "../Include/Common.h" +#include "../Include/Types.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + +class TIntermediate; + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator { + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + // + // Unary operators + // + + EOpNegative, + EOpLogicalNot, + EOpVectorLogicalNot, + EOpBitwiseNot, + + EOpPostIncrement, + EOpPostDecrement, + EOpPreIncrement, + EOpPreDecrement, + + EOpCopyObject, + + // (u)int* -> bool + EOpConvInt8ToBool, + EOpConvUint8ToBool, + EOpConvInt16ToBool, + EOpConvUint16ToBool, + EOpConvIntToBool, + EOpConvUintToBool, + EOpConvInt64ToBool, + EOpConvUint64ToBool, + + // float* -> bool + EOpConvFloat16ToBool, + EOpConvFloatToBool, + EOpConvDoubleToBool, + + // bool -> (u)int* + EOpConvBoolToInt8, + EOpConvBoolToUint8, + EOpConvBoolToInt16, + EOpConvBoolToUint16, + EOpConvBoolToInt, + EOpConvBoolToUint, + EOpConvBoolToInt64, + EOpConvBoolToUint64, + + // bool -> float* + EOpConvBoolToFloat16, + EOpConvBoolToFloat, + EOpConvBoolToDouble, + + // int8_t -> (u)int* + EOpConvInt8ToInt16, + EOpConvInt8ToInt, + EOpConvInt8ToInt64, + EOpConvInt8ToUint8, + EOpConvInt8ToUint16, + EOpConvInt8ToUint, + EOpConvInt8ToUint64, + + // uint8_t -> (u)int* + EOpConvUint8ToInt8, + EOpConvUint8ToInt16, + EOpConvUint8ToInt, + EOpConvUint8ToInt64, + EOpConvUint8ToUint16, + EOpConvUint8ToUint, + EOpConvUint8ToUint64, + + // int8_t -> float* + EOpConvInt8ToFloat16, + EOpConvInt8ToFloat, + EOpConvInt8ToDouble, + + // uint8_t -> float* + EOpConvUint8ToFloat16, + EOpConvUint8ToFloat, + EOpConvUint8ToDouble, + + // int16_t -> (u)int* + EOpConvInt16ToInt8, + EOpConvInt16ToInt, + EOpConvInt16ToInt64, + EOpConvInt16ToUint8, + EOpConvInt16ToUint16, + EOpConvInt16ToUint, + EOpConvInt16ToUint64, + + // uint16_t -> (u)int* + EOpConvUint16ToInt8, + EOpConvUint16ToInt16, + EOpConvUint16ToInt, + EOpConvUint16ToInt64, + EOpConvUint16ToUint8, + EOpConvUint16ToUint, + EOpConvUint16ToUint64, + + // int16_t -> float* + EOpConvInt16ToFloat16, + EOpConvInt16ToFloat, + EOpConvInt16ToDouble, + + // uint16_t -> float* + EOpConvUint16ToFloat16, + EOpConvUint16ToFloat, + EOpConvUint16ToDouble, + + // int32_t -> (u)int* + EOpConvIntToInt8, + EOpConvIntToInt16, + EOpConvIntToInt64, + EOpConvIntToUint8, + EOpConvIntToUint16, + EOpConvIntToUint, + EOpConvIntToUint64, + + // uint32_t -> (u)int* + EOpConvUintToInt8, + EOpConvUintToInt16, + EOpConvUintToInt, + EOpConvUintToInt64, + EOpConvUintToUint8, + EOpConvUintToUint16, + EOpConvUintToUint64, + + // int32_t -> float* + EOpConvIntToFloat16, + EOpConvIntToFloat, + EOpConvIntToDouble, + + // uint32_t -> float* + EOpConvUintToFloat16, + EOpConvUintToFloat, + EOpConvUintToDouble, + + // int64_t -> (u)int* + EOpConvInt64ToInt8, + EOpConvInt64ToInt16, + EOpConvInt64ToInt, + EOpConvInt64ToUint8, + EOpConvInt64ToUint16, + EOpConvInt64ToUint, + EOpConvInt64ToUint64, + + // uint64_t -> (u)int* + EOpConvUint64ToInt8, + EOpConvUint64ToInt16, + EOpConvUint64ToInt, + EOpConvUint64ToInt64, + EOpConvUint64ToUint8, + EOpConvUint64ToUint16, + EOpConvUint64ToUint, + + // int64_t -> float* + EOpConvInt64ToFloat16, + EOpConvInt64ToFloat, + EOpConvInt64ToDouble, + + // uint64_t -> float* + EOpConvUint64ToFloat16, + EOpConvUint64ToFloat, + EOpConvUint64ToDouble, + + // float16_t -> (u)int* + EOpConvFloat16ToInt8, + EOpConvFloat16ToInt16, + EOpConvFloat16ToInt, + EOpConvFloat16ToInt64, + EOpConvFloat16ToUint8, + EOpConvFloat16ToUint16, + EOpConvFloat16ToUint, + EOpConvFloat16ToUint64, + + // float16_t -> float* + EOpConvFloat16ToFloat, + EOpConvFloat16ToDouble, + + // float -> (u)int* + EOpConvFloatToInt8, + EOpConvFloatToInt16, + EOpConvFloatToInt, + EOpConvFloatToInt64, + EOpConvFloatToUint8, + EOpConvFloatToUint16, + EOpConvFloatToUint, + EOpConvFloatToUint64, + + // float -> float* + EOpConvFloatToFloat16, + EOpConvFloatToDouble, + + // float64 _t-> (u)int* + EOpConvDoubleToInt8, + EOpConvDoubleToInt16, + EOpConvDoubleToInt, + EOpConvDoubleToInt64, + EOpConvDoubleToUint8, + EOpConvDoubleToUint16, + EOpConvDoubleToUint, + EOpConvDoubleToUint64, + + // float64_t -> float* + EOpConvDoubleToFloat16, + EOpConvDoubleToFloat, + + // uint64_t <-> pointer + EOpConvUint64ToPtr, + EOpConvPtrToUint64, + + // uvec2 <-> pointer + EOpConvUvec2ToPtr, + EOpConvPtrToUvec2, + + // + // binary operations + // + + EOpAdd, + EOpSub, + EOpMul, + EOpDiv, + EOpMod, + EOpRightShift, + EOpLeftShift, + EOpAnd, + EOpInclusiveOr, + EOpExclusiveOr, + EOpEqual, + EOpNotEqual, + EOpVectorEqual, + EOpVectorNotEqual, + EOpLessThan, + EOpGreaterThan, + EOpLessThanEqual, + EOpGreaterThanEqual, + EOpComma, + + EOpVectorTimesScalar, + EOpVectorTimesMatrix, + EOpMatrixTimesVector, + EOpMatrixTimesScalar, + + EOpLogicalOr, + EOpLogicalXor, + EOpLogicalAnd, + + EOpIndexDirect, + EOpIndexIndirect, + EOpIndexDirectStruct, + + EOpVectorSwizzle, + + EOpMethod, + EOpScoping, + + // + // Built-in functions mapped to operators + // + + EOpRadians, + EOpDegrees, + EOpSin, + EOpCos, + EOpTan, + EOpAsin, + EOpAcos, + EOpAtan, + EOpSinh, + EOpCosh, + EOpTanh, + EOpAsinh, + EOpAcosh, + EOpAtanh, + + EOpPow, + EOpExp, + EOpLog, + EOpExp2, + EOpLog2, + EOpSqrt, + EOpInverseSqrt, + + EOpAbs, + EOpSign, + EOpFloor, + EOpTrunc, + EOpRound, + EOpRoundEven, + EOpCeil, + EOpFract, + EOpModf, + EOpMin, + EOpMax, + EOpClamp, + EOpMix, + EOpStep, + EOpSmoothStep, + + EOpIsNan, + EOpIsInf, + + EOpFma, + + EOpFrexp, + EOpLdexp, + + EOpFloatBitsToInt, + EOpFloatBitsToUint, + EOpIntBitsToFloat, + EOpUintBitsToFloat, + EOpDoubleBitsToInt64, + EOpDoubleBitsToUint64, + EOpInt64BitsToDouble, + EOpUint64BitsToDouble, + EOpFloat16BitsToInt16, + EOpFloat16BitsToUint16, + EOpInt16BitsToFloat16, + EOpUint16BitsToFloat16, + EOpPackSnorm2x16, + EOpUnpackSnorm2x16, + EOpPackUnorm2x16, + EOpUnpackUnorm2x16, + EOpPackSnorm4x8, + EOpUnpackSnorm4x8, + EOpPackUnorm4x8, + EOpUnpackUnorm4x8, + EOpPackHalf2x16, + EOpUnpackHalf2x16, + EOpPackDouble2x32, + EOpUnpackDouble2x32, + EOpPackInt2x32, + EOpUnpackInt2x32, + EOpPackUint2x32, + EOpUnpackUint2x32, + EOpPackFloat2x16, + EOpUnpackFloat2x16, + EOpPackInt2x16, + EOpUnpackInt2x16, + EOpPackUint2x16, + EOpUnpackUint2x16, + EOpPackInt4x16, + EOpUnpackInt4x16, + EOpPackUint4x16, + EOpUnpackUint4x16, + EOpPack16, + EOpPack32, + EOpPack64, + EOpUnpack32, + EOpUnpack16, + EOpUnpack8, + + EOpLength, + EOpDistance, + EOpDot, + EOpCross, + EOpNormalize, + EOpFaceForward, + EOpReflect, + EOpRefract, + + EOpMin3, + EOpMax3, + EOpMid3, + + EOpDPdx, // Fragment only + EOpDPdy, // Fragment only + EOpFwidth, // Fragment only + EOpDPdxFine, // Fragment only + EOpDPdyFine, // Fragment only + EOpFwidthFine, // Fragment only + EOpDPdxCoarse, // Fragment only + EOpDPdyCoarse, // Fragment only + EOpFwidthCoarse, // Fragment only + + EOpInterpolateAtCentroid, // Fragment only + EOpInterpolateAtSample, // Fragment only + EOpInterpolateAtOffset, // Fragment only + EOpInterpolateAtVertex, + + EOpMatrixTimesMatrix, + EOpOuterProduct, + EOpDeterminant, + EOpMatrixInverse, + EOpTranspose, + + EOpFtransform, + + EOpNoise, + + EOpEmitVertex, // geometry only + EOpEndPrimitive, // geometry only + EOpEmitStreamVertex, // geometry only + EOpEndStreamPrimitive, // geometry only + + EOpBarrier, + EOpMemoryBarrier, + EOpMemoryBarrierAtomicCounter, + EOpMemoryBarrierBuffer, + EOpMemoryBarrierImage, + EOpMemoryBarrierShared, // compute only + EOpGroupMemoryBarrier, // compute only + + EOpBallot, + EOpReadInvocation, + EOpReadFirstInvocation, + + EOpAnyInvocation, + EOpAllInvocations, + EOpAllInvocationsEqual, + + EOpSubgroupGuardStart, + EOpSubgroupBarrier, + EOpSubgroupMemoryBarrier, + EOpSubgroupMemoryBarrierBuffer, + EOpSubgroupMemoryBarrierImage, + EOpSubgroupMemoryBarrierShared, // compute only + EOpSubgroupElect, + EOpSubgroupAll, + EOpSubgroupAny, + EOpSubgroupAllEqual, + EOpSubgroupBroadcast, + EOpSubgroupBroadcastFirst, + EOpSubgroupBallot, + EOpSubgroupInverseBallot, + EOpSubgroupBallotBitExtract, + EOpSubgroupBallotBitCount, + EOpSubgroupBallotInclusiveBitCount, + EOpSubgroupBallotExclusiveBitCount, + EOpSubgroupBallotFindLSB, + EOpSubgroupBallotFindMSB, + EOpSubgroupShuffle, + EOpSubgroupShuffleXor, + EOpSubgroupShuffleUp, + EOpSubgroupShuffleDown, + EOpSubgroupAdd, + EOpSubgroupMul, + EOpSubgroupMin, + EOpSubgroupMax, + EOpSubgroupAnd, + EOpSubgroupOr, + EOpSubgroupXor, + EOpSubgroupInclusiveAdd, + EOpSubgroupInclusiveMul, + EOpSubgroupInclusiveMin, + EOpSubgroupInclusiveMax, + EOpSubgroupInclusiveAnd, + EOpSubgroupInclusiveOr, + EOpSubgroupInclusiveXor, + EOpSubgroupExclusiveAdd, + EOpSubgroupExclusiveMul, + EOpSubgroupExclusiveMin, + EOpSubgroupExclusiveMax, + EOpSubgroupExclusiveAnd, + EOpSubgroupExclusiveOr, + EOpSubgroupExclusiveXor, + EOpSubgroupClusteredAdd, + EOpSubgroupClusteredMul, + EOpSubgroupClusteredMin, + EOpSubgroupClusteredMax, + EOpSubgroupClusteredAnd, + EOpSubgroupClusteredOr, + EOpSubgroupClusteredXor, + EOpSubgroupQuadBroadcast, + EOpSubgroupQuadSwapHorizontal, + EOpSubgroupQuadSwapVertical, + EOpSubgroupQuadSwapDiagonal, + + EOpSubgroupPartition, + EOpSubgroupPartitionedAdd, + EOpSubgroupPartitionedMul, + EOpSubgroupPartitionedMin, + EOpSubgroupPartitionedMax, + EOpSubgroupPartitionedAnd, + EOpSubgroupPartitionedOr, + EOpSubgroupPartitionedXor, + EOpSubgroupPartitionedInclusiveAdd, + EOpSubgroupPartitionedInclusiveMul, + EOpSubgroupPartitionedInclusiveMin, + EOpSubgroupPartitionedInclusiveMax, + EOpSubgroupPartitionedInclusiveAnd, + EOpSubgroupPartitionedInclusiveOr, + EOpSubgroupPartitionedInclusiveXor, + EOpSubgroupPartitionedExclusiveAdd, + EOpSubgroupPartitionedExclusiveMul, + EOpSubgroupPartitionedExclusiveMin, + EOpSubgroupPartitionedExclusiveMax, + EOpSubgroupPartitionedExclusiveAnd, + EOpSubgroupPartitionedExclusiveOr, + EOpSubgroupPartitionedExclusiveXor, + + EOpSubgroupGuardStop, + + EOpMinInvocations, + EOpMaxInvocations, + EOpAddInvocations, + EOpMinInvocationsNonUniform, + EOpMaxInvocationsNonUniform, + EOpAddInvocationsNonUniform, + EOpMinInvocationsInclusiveScan, + EOpMaxInvocationsInclusiveScan, + EOpAddInvocationsInclusiveScan, + EOpMinInvocationsInclusiveScanNonUniform, + EOpMaxInvocationsInclusiveScanNonUniform, + EOpAddInvocationsInclusiveScanNonUniform, + EOpMinInvocationsExclusiveScan, + EOpMaxInvocationsExclusiveScan, + EOpAddInvocationsExclusiveScan, + EOpMinInvocationsExclusiveScanNonUniform, + EOpMaxInvocationsExclusiveScanNonUniform, + EOpAddInvocationsExclusiveScanNonUniform, + EOpSwizzleInvocations, + EOpSwizzleInvocationsMasked, + EOpWriteInvocation, + EOpMbcnt, + + EOpCubeFaceIndex, + EOpCubeFaceCoord, + EOpTime, + + EOpAtomicAdd, + EOpAtomicMin, + EOpAtomicMax, + EOpAtomicAnd, + EOpAtomicOr, + EOpAtomicXor, + EOpAtomicExchange, + EOpAtomicCompSwap, + EOpAtomicLoad, + EOpAtomicStore, + + EOpAtomicCounterIncrement, // results in pre-increment value + EOpAtomicCounterDecrement, // results in post-decrement value + EOpAtomicCounter, + EOpAtomicCounterAdd, + EOpAtomicCounterSubtract, + EOpAtomicCounterMin, + EOpAtomicCounterMax, + EOpAtomicCounterAnd, + EOpAtomicCounterOr, + EOpAtomicCounterXor, + EOpAtomicCounterExchange, + EOpAtomicCounterCompSwap, + + EOpAny, + EOpAll, + + EOpCooperativeMatrixLoad, + EOpCooperativeMatrixStore, + EOpCooperativeMatrixMulAdd, + + EOpBeginInvocationInterlock, // Fragment only + EOpEndInvocationInterlock, // Fragment only + + EOpIsHelperInvocation, + + EOpDebugPrintf, + + // + // Branch + // + + EOpKill, // Fragment only + EOpReturn, + EOpBreak, + EOpContinue, + EOpCase, + EOpDefault, + EOpDemote, // Fragment only + + // + // Constructors + // + + EOpConstructGuardStart, + EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed + EOpConstructUint, + EOpConstructInt8, + EOpConstructUint8, + EOpConstructInt16, + EOpConstructUint16, + EOpConstructInt64, + EOpConstructUint64, + EOpConstructBool, + EOpConstructFloat, + EOpConstructDouble, + // Keep vector and matrix constructors in a consistent relative order for + // TParseContext::constructBuiltIn, which converts between 8/16/32 bit + // vector constructors + EOpConstructVec2, + EOpConstructVec3, + EOpConstructVec4, + EOpConstructMat2x2, + EOpConstructMat2x3, + EOpConstructMat2x4, + EOpConstructMat3x2, + EOpConstructMat3x3, + EOpConstructMat3x4, + EOpConstructMat4x2, + EOpConstructMat4x3, + EOpConstructMat4x4, + EOpConstructDVec2, + EOpConstructDVec3, + EOpConstructDVec4, + EOpConstructBVec2, + EOpConstructBVec3, + EOpConstructBVec4, + EOpConstructI8Vec2, + EOpConstructI8Vec3, + EOpConstructI8Vec4, + EOpConstructU8Vec2, + EOpConstructU8Vec3, + EOpConstructU8Vec4, + EOpConstructI16Vec2, + EOpConstructI16Vec3, + EOpConstructI16Vec4, + EOpConstructU16Vec2, + EOpConstructU16Vec3, + EOpConstructU16Vec4, + EOpConstructIVec2, + EOpConstructIVec3, + EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, + EOpConstructI64Vec2, + EOpConstructI64Vec3, + EOpConstructI64Vec4, + EOpConstructU64Vec2, + EOpConstructU64Vec3, + EOpConstructU64Vec4, + EOpConstructDMat2x2, + EOpConstructDMat2x3, + EOpConstructDMat2x4, + EOpConstructDMat3x2, + EOpConstructDMat3x3, + EOpConstructDMat3x4, + EOpConstructDMat4x2, + EOpConstructDMat4x3, + EOpConstructDMat4x4, + EOpConstructIMat2x2, + EOpConstructIMat2x3, + EOpConstructIMat2x4, + EOpConstructIMat3x2, + EOpConstructIMat3x3, + EOpConstructIMat3x4, + EOpConstructIMat4x2, + EOpConstructIMat4x3, + EOpConstructIMat4x4, + EOpConstructUMat2x2, + EOpConstructUMat2x3, + EOpConstructUMat2x4, + EOpConstructUMat3x2, + EOpConstructUMat3x3, + EOpConstructUMat3x4, + EOpConstructUMat4x2, + EOpConstructUMat4x3, + EOpConstructUMat4x4, + EOpConstructBMat2x2, + EOpConstructBMat2x3, + EOpConstructBMat2x4, + EOpConstructBMat3x2, + EOpConstructBMat3x3, + EOpConstructBMat3x4, + EOpConstructBMat4x2, + EOpConstructBMat4x3, + EOpConstructBMat4x4, + EOpConstructFloat16, + EOpConstructF16Vec2, + EOpConstructF16Vec3, + EOpConstructF16Vec4, + EOpConstructF16Mat2x2, + EOpConstructF16Mat2x3, + EOpConstructF16Mat2x4, + EOpConstructF16Mat3x2, + EOpConstructF16Mat3x3, + EOpConstructF16Mat3x4, + EOpConstructF16Mat4x2, + EOpConstructF16Mat4x3, + EOpConstructF16Mat4x4, + EOpConstructStruct, + EOpConstructTextureSampler, + EOpConstructNonuniform, // expected to be transformed away, not present in final AST + EOpConstructReference, + EOpConstructCooperativeMatrix, + EOpConstructGuardEnd, + + // + // moves + // + + EOpAssign, + EOpAddAssign, + EOpSubAssign, + EOpMulAssign, + EOpVectorTimesMatrixAssign, + EOpVectorTimesScalarAssign, + EOpMatrixTimesScalarAssign, + EOpMatrixTimesMatrixAssign, + EOpDivAssign, + EOpModAssign, + EOpAndAssign, + EOpInclusiveOrAssign, + EOpExclusiveOrAssign, + EOpLeftShiftAssign, + EOpRightShiftAssign, + + // + // Array operators + // + + // Can apply to arrays, vectors, or matrices. + // Can be decomposed to a constant at compile time, but this does not always happen, + // due to link-time effects. So, consumer can expect either a link-time sized or + // run-time sized array. + EOpArrayLength, + + // + // Image operations + // + + EOpImageGuardBegin, + + EOpImageQuerySize, + EOpImageQuerySamples, + EOpImageLoad, + EOpImageStore, + EOpImageLoadLod, + EOpImageStoreLod, + EOpImageAtomicAdd, + EOpImageAtomicMin, + EOpImageAtomicMax, + EOpImageAtomicAnd, + EOpImageAtomicOr, + EOpImageAtomicXor, + EOpImageAtomicExchange, + EOpImageAtomicCompSwap, + EOpImageAtomicLoad, + EOpImageAtomicStore, + + EOpSubpassLoad, + EOpSubpassLoadMS, + EOpSparseImageLoad, + EOpSparseImageLoadLod, + + EOpImageGuardEnd, + + // + // Texture operations + // + + EOpTextureGuardBegin, + + EOpTextureQuerySize, + EOpTextureQueryLod, + EOpTextureQueryLevels, + EOpTextureQuerySamples, + + EOpSamplingGuardBegin, + + EOpTexture, + EOpTextureProj, + EOpTextureLod, + EOpTextureOffset, + EOpTextureFetch, + EOpTextureFetchOffset, + EOpTextureProjOffset, + EOpTextureLodOffset, + EOpTextureProjLod, + EOpTextureProjLodOffset, + EOpTextureGrad, + EOpTextureGradOffset, + EOpTextureProjGrad, + EOpTextureProjGradOffset, + EOpTextureGather, + EOpTextureGatherOffset, + EOpTextureGatherOffsets, + EOpTextureClamp, + EOpTextureOffsetClamp, + EOpTextureGradClamp, + EOpTextureGradOffsetClamp, + EOpTextureGatherLod, + EOpTextureGatherLodOffset, + EOpTextureGatherLodOffsets, + EOpFragmentMaskFetch, + EOpFragmentFetch, + + EOpSparseTextureGuardBegin, + + EOpSparseTexture, + EOpSparseTextureLod, + EOpSparseTextureOffset, + EOpSparseTextureFetch, + EOpSparseTextureFetchOffset, + EOpSparseTextureLodOffset, + EOpSparseTextureGrad, + EOpSparseTextureGradOffset, + EOpSparseTextureGather, + EOpSparseTextureGatherOffset, + EOpSparseTextureGatherOffsets, + EOpSparseTexelsResident, + EOpSparseTextureClamp, + EOpSparseTextureOffsetClamp, + EOpSparseTextureGradClamp, + EOpSparseTextureGradOffsetClamp, + EOpSparseTextureGatherLod, + EOpSparseTextureGatherLodOffset, + EOpSparseTextureGatherLodOffsets, + + EOpSparseTextureGuardEnd, + + EOpImageFootprintGuardBegin, + EOpImageSampleFootprintNV, + EOpImageSampleFootprintClampNV, + EOpImageSampleFootprintLodNV, + EOpImageSampleFootprintGradNV, + EOpImageSampleFootprintGradClampNV, + EOpImageFootprintGuardEnd, + EOpSamplingGuardEnd, + EOpTextureGuardEnd, + + // + // Integer operations + // + + EOpAddCarry, + EOpSubBorrow, + EOpUMulExtended, + EOpIMulExtended, + EOpBitfieldExtract, + EOpBitfieldInsert, + EOpBitFieldReverse, + EOpBitCount, + EOpFindLSB, + EOpFindMSB, + + EOpCountLeadingZeros, + EOpCountTrailingZeros, + EOpAbsDifference, + EOpAddSaturate, + EOpSubSaturate, + EOpAverage, + EOpAverageRounded, + EOpMul32x16, + + EOpTrace, + EOpReportIntersection, + EOpIgnoreIntersection, + EOpTerminateRay, + EOpExecuteCallable, + EOpWritePackedPrimitiveIndices4x8NV, + + // + // GL_EXT_ray_query operations + // + + EOpRayQueryInitialize, + EOpRayQueryTerminate, + EOpRayQueryGenerateIntersection, + EOpRayQueryConfirmIntersection, + EOpRayQueryProceed, + EOpRayQueryGetIntersectionType, + EOpRayQueryGetRayTMin, + EOpRayQueryGetRayFlags, + EOpRayQueryGetIntersectionT, + EOpRayQueryGetIntersectionInstanceCustomIndex, + EOpRayQueryGetIntersectionInstanceId, + EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, + EOpRayQueryGetIntersectionGeometryIndex, + EOpRayQueryGetIntersectionPrimitiveIndex, + EOpRayQueryGetIntersectionBarycentrics, + EOpRayQueryGetIntersectionFrontFace, + EOpRayQueryGetIntersectionCandidateAABBOpaque, + EOpRayQueryGetIntersectionObjectRayDirection, + EOpRayQueryGetIntersectionObjectRayOrigin, + EOpRayQueryGetWorldRayDirection, + EOpRayQueryGetWorldRayOrigin, + EOpRayQueryGetIntersectionObjectToWorld, + EOpRayQueryGetIntersectionWorldToObject, + + // + // HLSL operations + // + + EOpClip, // discard if input value < 0 + EOpIsFinite, + EOpLog10, // base 10 log + EOpRcp, // 1/x + EOpSaturate, // clamp from 0 to 1 + EOpSinCos, // sin and cos in out parameters + EOpGenMul, // mul(x,y) on any of mat/vec/scalars + EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w + EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return + EOpInterlockedAnd, // ... + EOpInterlockedCompareExchange, // ... + EOpInterlockedCompareStore, // ... + EOpInterlockedExchange, // ... + EOpInterlockedMax, // ... + EOpInterlockedMin, // ... + EOpInterlockedOr, // ... + EOpInterlockedXor, // ... + EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents + EOpDeviceMemoryBarrier, // ... + EOpDeviceMemoryBarrierWithGroupSync, // ... + EOpWorkgroupMemoryBarrier, // ... + EOpWorkgroupMemoryBarrierWithGroupSync, // ... + EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid + EOpF32tof16, // HLSL conversion: half of a PackHalf2x16 + EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16 + EOpLit, // HLSL lighting coefficient vector + EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture + EOpAsDouble, // slightly different from EOpUint64BitsToDouble + EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range + + EOpMethodSample, // Texture object methods. These are translated to existing + EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that + EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodSampleCmpLevelZero, // ... + EOpMethodSampleGrad, // ... + EOpMethodSampleLevel, // ... + EOpMethodLoad, // ... + EOpMethodGetDimensions, // ... + EOpMethodGetSamplePosition, // ... + EOpMethodGather, // ... + EOpMethodCalculateLevelOfDetail, // ... + EOpMethodCalculateLevelOfDetailUnclamped, // ... + + // Load already defined above for textures + EOpMethodLoad2, // Structure buffer object methods. These are translated to existing + EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that + EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods(). + EOpMethodStore, // ... + EOpMethodStore2, // ... + EOpMethodStore3, // ... + EOpMethodStore4, // ... + EOpMethodIncrementCounter, // ... + EOpMethodDecrementCounter, // ... + // EOpMethodAppend is defined for geo shaders below + EOpMethodConsume, + + // SM5 texture methods + EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about + EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily + EOpMethodGatherBlue, // because HLSL arguments are slightly different. + EOpMethodGatherAlpha, // ... + EOpMethodGatherCmp, // ... + EOpMethodGatherCmpRed, // ... + EOpMethodGatherCmpGreen, // ... + EOpMethodGatherCmpBlue, // ... + EOpMethodGatherCmpAlpha, // ... + + // geometry methods + EOpMethodAppend, // Geometry shader methods + EOpMethodRestartStrip, // ... + + // matrix + EOpMatrixSwizzle, // select multiple matrix components (non-column) + + // SM6 wave ops + EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize. + EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID. + EOpWaveActiveCountBits, // Will decompose to subgroupBallotBitCount(subgroupBallot()). + EOpWavePrefixCountBits, // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()). + + // Shader Clock Ops + EOpReadClockSubgroupKHR, + EOpReadClockDeviceKHR, +}; + +class TIntermTraverser; +class TIntermOperator; +class TIntermAggregate; +class TIntermUnary; +class TIntermBinary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermSwitch; +class TIntermBranch; +class TIntermTyped; +class TIntermMethod; +class TIntermSymbol; +class TIntermLoop; + +} // end namespace glslang + +// +// Base class for the tree nodes +// +// (Put outside the glslang namespace, as it's used as part of the external interface.) +// +class TIntermNode { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + + TIntermNode() { loc.init(); } + virtual const glslang::TSourceLoc& getLoc() const { return loc; } + virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; } + virtual void traverse(glslang::TIntermTraverser*) = 0; + virtual glslang::TIntermTyped* getAsTyped() { return 0; } + virtual glslang::TIntermOperator* getAsOperator() { return 0; } + virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } + virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } + virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } + virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } + virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } + virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } + virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } + virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } + virtual glslang::TIntermLoop* getAsLoopNode() { return 0; } + + virtual const glslang::TIntermTyped* getAsTyped() const { return 0; } + virtual const glslang::TIntermOperator* getAsOperator() const { return 0; } + virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; } + virtual const glslang::TIntermAggregate* getAsAggregate() const { return 0; } + virtual const glslang::TIntermUnary* getAsUnaryNode() const { return 0; } + virtual const glslang::TIntermBinary* getAsBinaryNode() const { return 0; } + virtual const glslang::TIntermSelection* getAsSelectionNode() const { return 0; } + virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return 0; } + virtual const glslang::TIntermMethod* getAsMethodNode() const { return 0; } + virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return 0; } + virtual const glslang::TIntermBranch* getAsBranchNode() const { return 0; } + virtual const glslang::TIntermLoop* getAsLoopNode() const { return 0; } + virtual ~TIntermNode() { } + +protected: + TIntermNode(const TIntermNode&); + TIntermNode& operator=(const TIntermNode&); + glslang::TSourceLoc loc; +}; + +namespace glslang { + +// +// This is just to help yacc. +// +struct TIntermNodePair { + TIntermNode* node1; + TIntermNode* node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode { +public: + TIntermTyped(const TType& t) { type.shallowCopy(t); } + TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); } + virtual TIntermTyped* getAsTyped() { return this; } + virtual const TIntermTyped* getAsTyped() const { return this; } + virtual void setType(const TType& t) { type.shallowCopy(t); } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { return type; } + + virtual TBasicType getBasicType() const { return type.getBasicType(); } + virtual TQualifier& getQualifier() { return type.getQualifier(); } + virtual const TQualifier& getQualifier() const { return type.getQualifier(); } + virtual void propagatePrecision(TPrecisionQualifier); + virtual int getVectorSize() const { return type.getVectorSize(); } + virtual int getMatrixCols() const { return type.getMatrixCols(); } + virtual int getMatrixRows() const { return type.getMatrixRows(); } + virtual bool isMatrix() const { return type.isMatrix(); } + virtual bool isArray() const { return type.isArray(); } + virtual bool isVector() const { return type.isVector(); } + virtual bool isScalar() const { return type.isScalar(); } + virtual bool isStruct() const { return type.isStruct(); } + virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } + virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } + bool isAtomic() const { return type.isAtomic(); } + bool isReference() const { return type.isReference(); } + TString getCompleteString() const { return type.getCompleteString(); } + +protected: + TIntermTyped& operator=(const TIntermTyped&); + TType type; +}; + +// +// Handle for, do-while, and while loops. +// +class TIntermLoop : public TIntermNode { +public: + TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : + body(aBody), + test(aTest), + terminal(aTerminal), + first(testFirst), + unroll(false), + dontUnroll(false), + dependency(0), + minIterations(0), + maxIterations(iterationsInfinite), + iterationMultiple(1), + peelCount(0), + partialCount(0) + { } + + virtual TIntermLoop* getAsLoopNode() { return this; } + virtual const TIntermLoop* getAsLoopNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TIntermNode* getBody() const { return body; } + TIntermTyped* getTest() const { return test; } + TIntermTyped* getTerminal() const { return terminal; } + bool testFirst() const { return first; } + + void setUnroll() { unroll = true; } + void setDontUnroll() { + dontUnroll = true; + peelCount = 0; + partialCount = 0; + } + bool getUnroll() const { return unroll; } + bool getDontUnroll() const { return dontUnroll; } + + static const unsigned int dependencyInfinite = 0xFFFFFFFF; + static const unsigned int iterationsInfinite = 0xFFFFFFFF; + void setLoopDependency(int d) { dependency = d; } + int getLoopDependency() const { return dependency; } + + void setMinIterations(unsigned int v) { minIterations = v; } + unsigned int getMinIterations() const { return minIterations; } + void setMaxIterations(unsigned int v) { maxIterations = v; } + unsigned int getMaxIterations() const { return maxIterations; } + void setIterationMultiple(unsigned int v) { iterationMultiple = v; } + unsigned int getIterationMultiple() const { return iterationMultiple; } + void setPeelCount(unsigned int v) { + peelCount = v; + dontUnroll = false; + } + unsigned int getPeelCount() const { return peelCount; } + void setPartialCount(unsigned int v) { + partialCount = v; + dontUnroll = false; + } + unsigned int getPartialCount() const { return partialCount; } + +protected: + TIntermNode* body; // code to loop over + TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops + TIntermTyped* terminal; // exists for for-loops + bool first; // true for while and for, not for do-while + bool unroll; // true if unroll requested + bool dontUnroll; // true if request to not unroll + unsigned int dependency; // loop dependency hint; 0 means not set or unknown + unsigned int minIterations; // as per the SPIR-V specification + unsigned int maxIterations; // as per the SPIR-V specification + unsigned int iterationMultiple; // as per the SPIR-V specification + unsigned int peelCount; // as per the SPIR-V specification + unsigned int partialCount; // as per the SPIR-V specification +}; + +// +// Handle case, break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode { +public: + TIntermBranch(TOperator op, TIntermTyped* e) : + flowOp(op), + expression(e) { } + virtual TIntermBranch* getAsBranchNode() { return this; } + virtual const TIntermBranch* getAsBranchNode() const { return this; } + virtual void traverse(TIntermTraverser*); + TOperator getFlowOp() const { return flowOp; } + TIntermTyped* getExpression() const { return expression; } + void setExpression(TIntermTyped* pExpression) { expression = pExpression; } +protected: + TOperator flowOp; + TIntermTyped* expression; +}; + +// +// Represent method names before seeing their calling signature +// or resolving them to operations. Just an expression as the base object +// and a textural name. +// +class TIntermMethod : public TIntermTyped { +public: + TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { } + virtual TIntermMethod* getAsMethodNode() { return this; } + virtual const TIntermMethod* getAsMethodNode() const { return this; } + virtual const TString& getMethodName() const { return method; } + virtual TIntermTyped* getObject() const { return object; } + virtual void traverse(TIntermTraverser*); +protected: + TIntermTyped* object; + TString method; +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped { +public: + // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from + // per process threadPoolAllocator, then it causes increased memory usage per compile + // it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int i, const TString& n, const TType& t) + : TIntermTyped(t), id(i), +#ifndef GLSLANG_WEB + flattenSubset(-1), +#endif + constSubtree(nullptr) + { name = n; } + virtual int getId() const { return id; } + virtual void changeId(int i) { id = i; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual TIntermSymbol* getAsSymbolNode() { return this; } + virtual const TIntermSymbol* getAsSymbolNode() const { return this; } + void setConstArray(const TConstUnionArray& c) { constArray = c; } + const TConstUnionArray& getConstArray() const { return constArray; } + void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + TIntermTyped* getConstSubtree() const { return constSubtree; } +#ifndef GLSLANG_WEB + void setFlattenSubset(int subset) { flattenSubset = subset; } + int getFlattenSubset() const { return flattenSubset; } // -1 means full object +#endif + + // This is meant for cases where a node has already been constructed, and + // later on, it becomes necessary to switch to a different symbol. + virtual void switchId(int newId) { id = newId; } + +protected: + int id; // the unique id of the symbol this node represents +#ifndef GLSLANG_WEB + int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced +#endif + TString name; // the name of the symbol this node represents + TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value + TIntermTyped* constSubtree; +}; + +class TIntermConstantUnion : public TIntermTyped { +public: + TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } + const TConstUnionArray& getConstArray() const { return constArray; } + virtual TIntermConstantUnion* getAsConstantUnion() { return this; } + virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const; + virtual TIntermTyped* fold(TOperator, const TType&) const; + void setLiteral() { literal = true; } + void setExpression() { literal = false; } + bool isLiteral() const { return literal; } + +protected: + TIntermConstantUnion& operator=(const TIntermConstantUnion&); + + const TConstUnionArray constArray; + bool literal; // true if node represents a literal in the source code +}; + +// Represent the independent aspects of a texturing TOperator +struct TCrackedTextureOp { + bool query; + bool proj; + bool lod; + bool fetch; + bool offset; + bool offsets; + bool gather; + bool grad; + bool subpass; + bool lodClamp; + bool fragMask; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped { +public: + virtual TIntermOperator* getAsOperator() { return this; } + virtual const TIntermOperator* getAsOperator() const { return this; } + TOperator getOp() const { return op; } + void setOp(TOperator newOp) { op = newOp; } + bool modifiesState() const; + bool isConstructor() const; + bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } + bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } +#ifdef GLSLANG_WEB + bool isImage() const { return false; } + bool isSparseTexture() const { return false; } + bool isImageFootprint() const { return false; } + bool isSparseImage() const { return false; } + bool isSubgroup() const { return false; } +#else + bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } + bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } + bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; } + bool isSparseImage() const { return op == EOpSparseImageLoad; } + bool isSubgroup() const { return op > EOpSubgroupGuardStart && op < EOpSubgroupGuardStop; } +#endif + + void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } + TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ? + operationPrecision : + type.getQualifier().precision; } + TString getCompleteString() const + { + TString cs = type.getCompleteString(); + if (getOperationPrecision() != type.getQualifier().precision) { + cs += ", operation at "; + cs += GetPrecisionQualifierString(getOperationPrecision()); + } + + return cs; + } + + // Crack the op into the individual dimensions of texturing operation. + void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const + { + cracked.query = false; + cracked.proj = false; + cracked.lod = false; + cracked.fetch = false; + cracked.offset = false; + cracked.offsets = false; + cracked.gather = false; + cracked.grad = false; + cracked.subpass = false; + cracked.lodClamp = false; + cracked.fragMask = false; + + switch (op) { + case EOpImageQuerySize: + case EOpImageQuerySamples: + case EOpTextureQuerySize: + case EOpTextureQueryLod: + case EOpTextureQueryLevels: + case EOpTextureQuerySamples: + case EOpSparseTexelsResident: + cracked.query = true; + break; + case EOpTexture: + case EOpSparseTexture: + break; + case EOpTextureProj: + cracked.proj = true; + break; + case EOpTextureLod: + case EOpSparseTextureLod: + cracked.lod = true; + break; + case EOpTextureOffset: + case EOpSparseTextureOffset: + cracked.offset = true; + break; + case EOpTextureFetch: + case EOpSparseTextureFetch: + cracked.fetch = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureFetchOffset: + case EOpSparseTextureFetchOffset: + cracked.fetch = true; + cracked.offset = true; + if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) + cracked.lod = true; + break; + case EOpTextureProjOffset: + cracked.offset = true; + cracked.proj = true; + break; + case EOpTextureLodOffset: + case EOpSparseTextureLodOffset: + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureProjLod: + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureProjLodOffset: + cracked.offset = true; + cracked.lod = true; + cracked.proj = true; + break; + case EOpTextureGrad: + case EOpSparseTextureGrad: + cracked.grad = true; + break; + case EOpTextureGradOffset: + case EOpSparseTextureGradOffset: + cracked.grad = true; + cracked.offset = true; + break; + case EOpTextureProjGrad: + cracked.grad = true; + cracked.proj = true; + break; + case EOpTextureProjGradOffset: + cracked.grad = true; + cracked.offset = true; + cracked.proj = true; + break; +#ifndef GLSLANG_WEB + case EOpTextureClamp: + case EOpSparseTextureClamp: + cracked.lodClamp = true; + break; + case EOpTextureOffsetClamp: + case EOpSparseTextureOffsetClamp: + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGradClamp: + case EOpSparseTextureGradClamp: + cracked.grad = true; + cracked.lodClamp = true; + break; + case EOpTextureGradOffsetClamp: + case EOpSparseTextureGradOffsetClamp: + cracked.grad = true; + cracked.offset = true; + cracked.lodClamp = true; + break; + case EOpTextureGather: + case EOpSparseTextureGather: + cracked.gather = true; + break; + case EOpTextureGatherOffset: + case EOpSparseTextureGatherOffset: + cracked.gather = true; + cracked.offset = true; + break; + case EOpTextureGatherOffsets: + case EOpSparseTextureGatherOffsets: + cracked.gather = true; + cracked.offsets = true; + break; + case EOpTextureGatherLod: + case EOpSparseTextureGatherLod: + cracked.gather = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffset: + case EOpSparseTextureGatherLodOffset: + cracked.gather = true; + cracked.offset = true; + cracked.lod = true; + break; + case EOpTextureGatherLodOffsets: + case EOpSparseTextureGatherLodOffsets: + cracked.gather = true; + cracked.offsets = true; + cracked.lod = true; + break; + case EOpImageLoadLod: + case EOpImageStoreLod: + case EOpSparseImageLoadLod: + cracked.lod = true; + break; + case EOpFragmentMaskFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpFragmentFetch: + cracked.subpass = sampler.dim == EsdSubpass; + cracked.fragMask = true; + break; + case EOpImageSampleFootprintNV: + break; + case EOpImageSampleFootprintClampNV: + cracked.lodClamp = true; + break; + case EOpImageSampleFootprintLodNV: + cracked.lod = true; + break; + case EOpImageSampleFootprintGradNV: + cracked.grad = true; + break; + case EOpImageSampleFootprintGradClampNV: + cracked.lodClamp = true; + cracked.grad = true; + break; + case EOpSubpassLoad: + case EOpSubpassLoadMS: + cracked.subpass = true; + break; +#endif + default: + break; + } + } + +protected: + TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {} + TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {} + TOperator op; + // The result precision is in the inherited TType, and is usually meant to be both + // the operation precision and the result precision. However, some more complex things, + // like built-in function calls, distinguish between the two, in which case non-EqpNone + // 'operationPrecision' overrides the result precision as far as operation precision + // is concerned. + TPrecisionQualifier operationPrecision; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator { +public: + TIntermBinary(TOperator o) : TIntermOperator(o) {} + virtual void traverse(TIntermTraverser*); + virtual void setLeft(TIntermTyped* n) { left = n; } + virtual void setRight(TIntermTyped* n) { right = n; } + virtual TIntermTyped* getLeft() const { return left; } + virtual TIntermTyped* getRight() const { return right; } + virtual TIntermBinary* getAsBinaryNode() { return this; } + virtual const TIntermBinary* getAsBinaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* left; + TIntermTyped* right; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator { +public: + TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} + TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} + virtual void traverse(TIntermTraverser*); + virtual void setOperand(TIntermTyped* o) { operand = o; } + virtual TIntermTyped* getOperand() { return operand; } + virtual const TIntermTyped* getOperand() const { return operand; } + virtual TIntermUnary* getAsUnaryNode() { return this; } + virtual const TIntermUnary* getAsUnaryNode() const { return this; } + virtual void updatePrecision(); +protected: + TIntermTyped* operand; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator { +public: + TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { } + TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { } + ~TIntermAggregate() { delete pragmaTable; } + virtual TIntermAggregate* getAsAggregate() { return this; } + virtual const TIntermAggregate* getAsAggregate() const { return this; } + virtual void setOperator(TOperator o) { op = o; } + virtual TIntermSequence& getSequence() { return sequence; } + virtual const TIntermSequence& getSequence() const { return sequence; } + virtual void setName(const TString& n) { name = n; } + virtual const TString& getName() const { return name; } + virtual void traverse(TIntermTraverser*); + virtual void setUserDefined() { userDefined = true; } + virtual bool isUserDefined() { return userDefined; } + virtual TQualifierList& getQualifierList() { return qualifier; } + virtual const TQualifierList& getQualifierList() const { return qualifier; } + void setOptimize(bool o) { optimize = o; } + void setDebug(bool d) { debug = d; } + bool getOptimize() const { return optimize; } + bool getDebug() const { return debug; } + void setPragmaTable(const TPragmaTable& pTable); + const TPragmaTable& getPragmaTable() const { return *pragmaTable; } +protected: + TIntermAggregate(const TIntermAggregate&); // disallow copy constructor + TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator + TIntermSequence sequence; + TQualifierList qualifier; + TString name; + bool userDefined; // used for user defined function names + bool optimize; + bool debug; + TPragmaTable* pragmaTable; +}; + +// +// For if tests. +// +class TIntermSelection : public TIntermTyped { +public: + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : + TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : + TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), + shortCircuit(true), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermTyped* getCondition() const { return condition; } + virtual TIntermNode* getTrueBlock() const { return trueBlock; } + virtual TIntermNode* getFalseBlock() const { return falseBlock; } + virtual TIntermSelection* getAsSelectionNode() { return this; } + virtual const TIntermSelection* getAsSelectionNode() const { return this; } + + void setNoShortCircuit() { shortCircuit = false; } + bool getShortCircuit() const { return shortCircuit; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermNode* trueBlock; + TIntermNode* falseBlock; + bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +// +// For switch statements. Designed use is that a switch will have sequence of nodes +// that are either case/default nodes or a *single* node that represents all the code +// in between (if any) consecutive case/defaults. So, a traversal need only deal with +// 0 or 1 nodes per case/default statement. +// +class TIntermSwitch : public TIntermNode { +public: + TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), + flatten(false), dontFlatten(false) {} + virtual void traverse(TIntermTraverser*); + virtual TIntermNode* getCondition() const { return condition; } + virtual TIntermAggregate* getBody() const { return body; } + virtual TIntermSwitch* getAsSwitchNode() { return this; } + virtual const TIntermSwitch* getAsSwitchNode() const { return this; } + + void setFlatten() { flatten = true; } + void setDontFlatten() { dontFlatten = true; } + bool getFlatten() const { return flatten; } + bool getDontFlatten() const { return dontFlatten; } + +protected: + TIntermTyped* condition; + TIntermAggregate* body; + bool flatten; // true if flatten requested + bool dontFlatten; // true if requested to not flatten +}; + +enum TVisit +{ + EvPreVisit, + EvInVisit, + EvPostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +// Explicitly set postVisit to true if you want post visiting, otherwise, +// filled in methods will only be called at pre-visit time (before processing +// the subtree). Similarly for inVisit for in-order visiting of nodes with +// multiple children. +// +// If you only want post-visits, explicitly turn off preVisit (and inVisit) +// and turn on postVisit. +// +// In general, for the visit*() methods, return true from interior nodes +// to have the traversal continue on to children. +// +// If you process children yourself, or don't want them processed, return false. +// +class TIntermTraverser { +public: + POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : + preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + depth(0), + maxDepth(0) { } + virtual ~TIntermTraverser() { } + + virtual void visitSymbol(TIntermSymbol*) { } + virtual void visitConstantUnion(TIntermConstantUnion*) { } + virtual bool visitBinary(TVisit, TIntermBinary*) { return true; } + virtual bool visitUnary(TVisit, TIntermUnary*) { return true; } + virtual bool visitSelection(TVisit, TIntermSelection*) { return true; } + virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; } + virtual bool visitLoop(TVisit, TIntermLoop*) { return true; } + virtual bool visitBranch(TVisit, TIntermBranch*) { return true; } + virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; } + + int getMaxDepth() const { return maxDepth; } + + void incrementDepth(TIntermNode *current) + { + depth++; + maxDepth = (std::max)(maxDepth, depth); + path.push_back(current); + } + + void decrementDepth() + { + depth--; + path.pop_back(); + } + + TIntermNode *getParentNode() + { + return path.size() == 0 ? NULL : path.back(); + } + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + +protected: + TIntermTraverser& operator=(TIntermTraverser&); + + int depth; + int maxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector path; +}; + +// KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if +// sized with the same symbol, involving no operations" +inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2) +{ + return node1->getAsSymbolNode() && node2->getAsSymbolNode() && + node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId(); +} + +} // end namespace glslang + +#endif // __INTERMEDIATE_H diff --git a/ios/include/glslang/Include/revision.h b/ios/include/glslang/Include/revision.h new file mode 100644 index 00000000..744c2fb4 --- /dev/null +++ b/ios/include/glslang/Include/revision.h @@ -0,0 +1,3 @@ +// This header is generated by the make-revision script. + +#define GLSLANG_PATCH_LEVEL 3743 diff --git a/ios/include/glslang/MachineIndependent/Initialize.h b/ios/include/glslang/MachineIndependent/Initialize.h new file mode 100644 index 00000000..ac8ec33e --- /dev/null +++ b/ios/include/glslang/MachineIndependent/Initialize.h @@ -0,0 +1,112 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 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 _INITIALIZE_INCLUDED_ +#define _INITIALIZE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../Include/Common.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "Versions.h" + +namespace glslang { + +// +// This is made to hold parseable strings for almost all the built-in +// functions and variables for one specific combination of version +// and profile. (Some still need to be added programmatically.) +// This is a base class for language-specific derivations, which +// can be used for language independent builtins. +// +// The strings are organized by +// commonBuiltins: intersection of all stages' built-ins, processed just once +// stageBuiltins[]: anything a stage needs that's not in commonBuiltins +// +class TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltInParseables(); + virtual ~TBuiltInParseables(); + virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0; + virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0; + virtual const TString& getCommonString() const { return commonBuiltins; } + virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; } + + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0; + virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0; + +protected: + TString commonBuiltins; + TString stageBuiltins[EShLangCount]; +}; + +// +// This is a GLSL specific derivation of TBuiltInParseables. To present a stable +// interface and match other similar code, it is called TBuiltIns, rather +// than TBuiltInParseablesGlsl. +// +class TBuiltIns : public TBuiltInParseables { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TBuiltIns(); + virtual ~TBuiltIns(); + void initialize(int version, EProfile, const SpvVersion& spvVersion); + void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage); + + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable); + void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources); + +protected: + void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion); + void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&); + void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion); + void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile); + void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile); + void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile); + + // Helpers for making textual representations of the permutations + // of texturing/imaging functions. + const char* postfixes[5]; + const char* prefixes[EbtNumTypes]; + int dimMap[EsdNumDims]; +}; + +} // end namespace glslang + +#endif // _INITIALIZE_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/LiveTraverser.h b/ios/include/glslang/MachineIndependent/LiveTraverser.h new file mode 100644 index 00000000..7333bc96 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/LiveTraverser.h @@ -0,0 +1,138 @@ +// +// Copyright (C) 2016 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. +// + +#pragma once + +#include "../Include/Common.h" +#include "reflection.h" +#include "localintermediate.h" + +#include "gl_types.h" + +#include +#include + +namespace glslang { + +// +// The traverser: mostly pass through, except +// - processing function-call nodes to push live functions onto the stack of functions to process +// - processing selection nodes to trim semantically dead code +// +// This is in the glslang namespace directly so it can be a friend of TReflection. +// This can be derived from to implement reflection database traversers or +// binding mappers: anything that wants to traverse the live subset of the tree. +// + +class TLiveTraverser : public TIntermTraverser { +public: + TLiveTraverser(const TIntermediate& i, bool traverseAll = false, + bool preVisit = true, bool inVisit = false, bool postVisit = false) : + TIntermTraverser(preVisit, inVisit, postVisit), + intermediate(i), traverseAll(traverseAll) + { } + + // + // Given a function name, find its subroot in the tree, and push it onto the stack of + // functions left to process. + // + void pushFunction(const TString& name) + { + TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); + for (unsigned int f = 0; f < globals.size(); ++f) { + TIntermAggregate* candidate = globals[f]->getAsAggregate(); + if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { + functions.push_back(candidate); + break; + } + } + } + + typedef std::list TFunctionStack; + TFunctionStack functions; + +protected: + // To catch which function calls are not dead, and hence which functions must be visited. + virtual bool visitAggregate(TVisit, TIntermAggregate* node) + { + if (!traverseAll) + if (node->getOp() == EOpFunctionCall) + addFunctionCall(node); + + return true; // traverse this subtree + } + + // To prune semantically dead paths. + virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node) + { + if (traverseAll) + return true; // traverse all code + + TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion(); + if (constant) { + // cull the path that is dead + if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock()) + node->getTrueBlock()->traverse(this); + if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock()) + node->getFalseBlock()->traverse(this); + + return false; // don't traverse any more, we did it all above + } else + return true; // traverse the whole subtree + } + + // Track live functions as well as uniforms, so that we don't visit dead functions + // and only visit each function once. + void addFunctionCall(TIntermAggregate* call) + { + // // just use the map to ensure we process each function at most once + if (liveFunctions.find(call->getName()) == liveFunctions.end()) { + liveFunctions.insert(call->getName()); + pushFunction(call->getName()); + } + } + + const TIntermediate& intermediate; + typedef std::unordered_set TLiveFunctions; + TLiveFunctions liveFunctions; + bool traverseAll; + +private: + // prevent copy & copy construct + TLiveTraverser(TLiveTraverser&); + TLiveTraverser& operator=(TLiveTraverser&); +}; + +} // namespace glslang diff --git a/ios/include/glslang/MachineIndependent/ParseHelper.h b/ios/include/glslang/MachineIndependent/ParseHelper.h new file mode 100644 index 00000000..20df6405 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/ParseHelper.h @@ -0,0 +1,525 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 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. +// + +// +// This header defines a two-level parse-helper hierarchy, derived from +// TParseVersions: +// - TParseContextBase: sharable across multiple parsers +// - TParseContext: GLSL specific helper +// + +#ifndef _PARSER_HELPER_INCLUDED_ +#define _PARSER_HELPER_INCLUDED_ + +#include +#include + +#include "parseVersions.h" +#include "../Include/ShHandle.h" +#include "SymbolTable.h" +#include "localintermediate.h" +#include "Scan.h" +#include "attribute.h" + +namespace glslang { + +struct TPragma { + TPragma(bool o, bool d) : optimize(o), debug(d) { } + bool optimize; + bool debug; + TPragmaTable pragmaTable; +}; + +class TScanContext; +class TPpContext; + +typedef std::set TIdSetType; + +// +// Sharable code (as well as what's in TParseVersions) across +// parse helpers. +// +class TParseContextBase : public TParseVersions { +public: + TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, + EProfile profile, const SpvVersion& spvVersion, EShLanguage language, + TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, + const TString* entryPoint = nullptr) + : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), + scopeMangler("::"), + symbolTable(symbolTable), + statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), + postEntryPointReturn(false), + contextPragma(true, false), + beginInvocationInterlockCount(0), endInvocationInterlockCount(0), + parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), + limits(resources.limits), + globalUniformBlock(nullptr), + globalUniformBinding(TQualifier::layoutBindingEnd), + globalUniformSet(TQualifier::layoutSetEnd) + { + if (entryPoint != nullptr) + sourceEntryPointName = *entryPoint; + } + virtual ~TParseContextBase() { } + +#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL) + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); +#endif + + virtual void setLimits(const TBuiltInResource&) = 0; + + void checkIndex(const TSourceLoc&, const TType&, int& index); + + EShLanguage getLanguage() const { return language; } + void setScanContext(TScanContext* c) { scanContext = c; } + TScanContext* getScanContext() const { return scanContext; } + void setPpContext(TPpContext* c) { ppContext = c; } + TPpContext* getPpContext() const { return ppContext; } + + virtual void setLineCallback(const std::function& func) { lineCallback = func; } + virtual void setExtensionCallback(const std::function& func) { extensionCallback = func; } + virtual void setVersionCallback(const std::function& func) { versionCallback = func; } + virtual void setPragmaCallback(const std::function&)>& func) { pragmaCallback = func; } + virtual void setErrorCallback(const std::function& func) { errorCallback = func; } + + virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; + virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; + virtual bool lineDirectiveShouldSetNextLine() const = 0; + virtual void handlePragma(const TSourceLoc&, const TVector&) = 0; + + virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; + + virtual void notifyVersion(int line, int version, const char* type_string) + { + if (versionCallback) + versionCallback(line, version, type_string); + } + virtual void notifyErrorDirective(int line, const char* error_message) + { + if (errorCallback) + errorCallback(line, error_message); + } + virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) + { + if (lineCallback) + lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); + } + virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) + { + if (extensionCallback) + extensionCallback(line, extension, behavior); + } + +#ifdef ENABLE_HLSL + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); +#endif + + // Potentially rename shader entry point function + void renameShaderFunction(TString*& name) const + { + // Replace the entry point name given in the shader with the real entry point name, + // if there is a substitution. + if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) + name = NewPoolTString(intermediate.getEntryPointName().c_str()); + } + + virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + + const char* const scopeMangler; + + // Basic parsing state, easily accessible to the grammar + + TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile + int statementNestingLevel; // 0 if outside all flow control or compound statements + int loopNestingLevel; // 0 if outside all loops + int structNestingLevel; // 0 if outside blocks and structures + int controlFlowNestingLevel; // 0 if outside all flow control + const TType* currentFunctionType; // the return type of the function that's currently being parsed + bool functionReturnsValue; // true if a non-void function has a return + // if inside a function, true if the function is the entry point and this is after a return statement + bool postEntryPointReturn; + // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting + TList switchSequenceStack; + // the statementNestingLevel the current switch statement is at, which must match the level of its case statements + TList switchLevel; + struct TPragma contextPragma; + int beginInvocationInterlockCount; + int endInvocationInterlockCount; + +protected: + TParseContextBase(TParseContextBase&); + TParseContextBase& operator=(TParseContextBase&); + + const bool parsingBuiltins; // true if parsing built-in symbols/functions + TVector linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving + TScanContext* scanContext; + TPpContext* ppContext; + TBuiltInResource resources; + TLimits& limits; + TString sourceEntryPointName; + + // These, if set, will be called when a line, pragma ... is preprocessed. + // They will be called with any parameters to the original directive. + std::function lineCallback; + std::function&)> pragmaCallback; + std::function versionCallback; + std::function extensionCallback; + std::function errorCallback; + + // see implementation for detail + const TFunction* selectFunction(const TVector, const TFunction&, + std::function, + std::function, + /* output */ bool& tie); + + virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, + TSwizzleSelectors&); + + // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) + TVariable* globalUniformBlock; // the actual block, inserted into the symbol table + unsigned int globalUniformBinding; // the block's binding number + unsigned int globalUniformSet; // the block's set number + int firstNewMember; // the index of the first member not yet inserted into the symbol table + // override this to set the language-specific name + virtual const char* getGlobalUniformBlockName() const { return ""; } + virtual void setUniformBlockDefaults(TType&) const { } + virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } + virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, TPrefixType prefix, + va_list args); + virtual void trackLinkage(TSymbol& symbol); + virtual void makeEditable(TSymbol*&); + virtual TVariable* getEditableVariable(const char* name); + virtual void finish(); +}; + +// +// Manage the state for when to respect precision qualifiers and when to warn about +// the defaults being different than might be expected. +// +class TPrecisionManager { +public: + TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } + virtual ~TPrecisionManager() {} + + void respectPrecisionQualifiers() { obey = true; } + bool respectingPrecisionQualifiers() const { return obey; } + bool shouldWarnAboutDefaults() const { return warn; } + void defaultWarningGiven() { warn = false; } + void warnAboutDefaults() { warn = true; } + void explicitIntDefaultSeen() + { + explicitIntDefault = true; + if (explicitFloatDefault) + warn = false; + } + void explicitFloatDefaultSeen() + { + explicitFloatDefault = true; + if (explicitIntDefault) + warn = false; + } + +protected: + bool obey; // respect precision qualifiers + bool warn; // need to give a warning about the defaults + bool explicitIntDefault; // user set the default for int/uint + bool explicitFloatDefault; // user set the default for float +}; + +// +// GLSL-specific parse helper. Should have GLSL in the name, but that's +// too big of a change for comparing branches at the moment, and perhaps +// impacts downstream consumers as well. +// +class TParseContext : public TParseContextBase { +public: + TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, + bool forwardCompatible = false, EShMessages messages = EShMsgDefault, + const TString* entryPoint = nullptr); + virtual ~TParseContext(); + + bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); } + void setPrecisionDefaults(); + + void setLimits(const TBuiltInResource&) override; + bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; + void parserError(const char* s); // for bison's yyerror + + void reservedErrorCheck(const TSourceLoc&, const TString&); + void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; + bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; + bool lineDirectiveShouldSetNextLine() const override; + bool builtInName(const TString&); + + void handlePragma(const TSourceLoc&, const TVector&) override; + TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); + TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); + +#ifndef GLSLANG_WEB + void makeEditable(TSymbol*&) override; + void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); +#endif + bool isIoResizeArray(const TType&) const; + void fixIoArraySize(const TSourceLoc&, TType&); + void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); + void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); + int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; + void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); + + TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); + TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); + TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); + void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); + TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); + TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); + TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); + TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); + void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); + TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); + void checkLocation(const TSourceLoc&, TOperator); + TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); + void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; + TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; + void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); + void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); + void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); + void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); + TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); + void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); + void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); + void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); + + void assignError(const TSourceLoc&, const char* op, TString left, TString right); + void unaryOpError(const TSourceLoc&, const char* op, TString operand); + void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); + void variableCheck(TIntermTyped*& nodePtr); + bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; + void constantValueCheck(TIntermTyped* node, const char* token); + void integerCheck(const TIntermTyped* node, const char* token); + void globalCheck(const TSourceLoc&, const char* token); + bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); + bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); + void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType); + bool arrayQualifierError(const TSourceLoc&, const TQualifier&); + bool arrayError(const TSourceLoc&, const TType&); + void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); + void structArrayCheck(const TSourceLoc&, const TType& structure); + void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); + void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); + bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); + void boolCheck(const TSourceLoc&, const TIntermTyped*); + void boolCheck(const TSourceLoc&, const TPublicType&); + void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); + void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); + void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); + void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); + void memberQualifierCheck(glslang::TPublicType&); + void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); + void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); + bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); + void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); + void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); + int computeSamplerTypeIndex(TSampler&); + TPrecisionQualifier getDefaultPrecision(TPublicType&); + void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); + void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); + bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); + TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); + void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); + void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); + void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); + void nestedBlockCheck(const TSourceLoc&); + void nestedStructCheck(const TSourceLoc&); + void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); + void opaqueCheck(const TSourceLoc&, const TType&, const char* op); + void referenceCheck(const TSourceLoc&, const TType&, const char* op); + void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); + void specializationCheck(const TSourceLoc&, const TType&, const char* op); + void structTypeCheck(const TSourceLoc&, TPublicType&); + void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); + void arrayLimitCheck(const TSourceLoc&, const TString&, int size); + void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); + + void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); + void constantIndexExpressionCheck(TIntermNode*); + + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); + void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); + void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); + void layoutObjectCheck(const TSourceLoc&, const TSymbol&); + void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); + void layoutTypeCheck(const TSourceLoc&, const TType&); + void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); + void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); + void fixOffset(const TSourceLoc&, TSymbol&); + + const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); + void declareTypeDefaults(const TSourceLoc&, const TPublicType&); + TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); + TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); + TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); + TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); + void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); + void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); + void blockStageIoCheck(const TSourceLoc&, const TQualifier&); + void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); + void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); + void fixXfbOffsets(TQualifier&, TTypeList&); + void fixBlockUniformOffsets(TQualifier&, TTypeList&); + void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); + void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); + void invariantCheck(const TSourceLoc&, const TQualifier&); + void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); + void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); + TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); + +#ifndef GLSLANG_WEB + TAttributeType attributeFromName(const TString& name) const; + TAttributes* makeAttributes(const TString& identifier) const; + TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; + TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; + + // Determine selection control from attributes + void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); + void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); + // Determine loop control from attributes + void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); +#endif + + void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); + +protected: + void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); + void inheritGlobalDefaults(TQualifier& dst) const; + TVariable* makeInternalVariable(const char* name, const TType&) const; + TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); + void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); + void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); + bool isRuntimeLength(const TIntermTyped&) const; + TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); + TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); +#ifndef GLSLANG_WEB + void finish() override; +#endif + +public: + // + // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access + // + + // Current state of parsing + bool inMain; // if inside a function, true if the function is main + const TString* blockName; + TQualifier currentBlockQualifier; + TPrecisionQualifier defaultPrecision[EbtNumTypes]; + TBuiltInResource resources; + TLimits& limits; + +protected: + TParseContext(TParseContext&); + TParseContext& operator=(TParseContext&); + + static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() + TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; + TPrecisionManager precisionManager; + TQualifier globalBufferDefaults; + TQualifier globalUniformDefaults; + TQualifier globalInputDefaults; + TQualifier globalOutputDefaults; + TString currentCaller; // name of last function body entered (not valid when at global scope) +#ifndef GLSLANG_WEB + int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point + bool anyIndexLimits; + TIdSetType inductiveLoopIds; + TVector needsIndexLimitationChecking; + + // + // Geometry shader input arrays: + // - array sizing is based on input primitive and/or explicit size + // + // Tessellation control output arrays: + // - array sizing is based on output layout(vertices=...) and/or explicit size + // + // Both: + // - array sizing is retroactive + // - built-in block redeclarations interact with this + // + // Design: + // - use a per-context "resize-list", a list of symbols whose array sizes + // can be fixed + // + // - the resize-list starts empty at beginning of user-shader compilation, it does + // not have built-ins in it + // + // - on built-in array use: copyUp() symbol and add it to the resize-list + // + // - on user array declaration: add it to the resize-list + // + // - on block redeclaration: copyUp() symbol and add it to the resize-list + // * note, that appropriately gives an error if redeclaring a block that + // was already used and hence already copied-up + // + // - on seeing a layout declaration that sizes the array, fix everything in the + // resize-list, giving errors for mismatch + // + // - on seeing an array size declaration, give errors on mismatch between it and previous + // array-sizing declarations + // + TVector ioArraySymbolResizeList; +#endif +}; + +} // end namespace glslang + +#endif // _PARSER_HELPER_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/RemoveTree.h b/ios/include/glslang/MachineIndependent/RemoveTree.h new file mode 100644 index 00000000..1ed01562 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/RemoveTree.h @@ -0,0 +1,41 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// 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 + +namespace glslang { + +void RemoveAllTreeNodes(TIntermNode*); + +} // end namespace glslang diff --git a/ios/include/glslang/MachineIndependent/Scan.h b/ios/include/glslang/MachineIndependent/Scan.h new file mode 100644 index 00000000..24b75cf7 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/Scan.h @@ -0,0 +1,276 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 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 _GLSLANG_SCAN_INCLUDED_ +#define _GLSLANG_SCAN_INCLUDED_ + +#include "Versions.h" + +namespace glslang { + +// Use a global end-of-input character, so no translation is needed across +// layers of encapsulation. Characters are all 8 bit, and positive, so there is +// no aliasing of character 255 onto -1, for example. +const int EndOfInput = -1; + +// +// A character scanner that seamlessly, on read-only strings, reads across an +// array of strings without assuming null termination. +// +class TInputScanner { +public: + TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, + int b = 0, int f = 0, bool single = false) : + numSources(n), + // up to this point, common usage is "char*", but now we need positive 8-bit characters + sources(reinterpret_cast(s)), + lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), + endOfFileReached(false) + { + loc = new TSourceLoc[numSources]; + for (int i = 0; i < numSources; ++i) { + loc[i].init(i - stringBias); + } + if (names != nullptr) { + for (int i = 0; i < numSources; ++i) + loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr; + } + loc[currentSource].line = 1; + logicalSourceLoc.init(1); + logicalSourceLoc.name = loc[0].name; + } + + virtual ~TInputScanner() + { + delete [] loc; + } + + // retrieve the next character and advance one character + int get() + { + int ret = peek(); + if (ret == EndOfInput) + return ret; + ++loc[currentSource].column; + ++logicalSourceLoc.column; + if (ret == '\n') { + ++loc[currentSource].line; + ++logicalSourceLoc.line; + logicalSourceLoc.column = 0; + loc[currentSource].column = 0; + } + advance(); + + return ret; + } + + // retrieve the next character, no advance + int peek() + { + if (currentSource >= numSources) { + endOfFileReached = true; + return EndOfInput; + } + // Make sure we do not read off the end of a string. + // N.B. Sources can have a length of 0. + int sourceToRead = currentSource; + size_t charToRead = currentChar; + while(charToRead >= lengths[sourceToRead]) { + charToRead = 0; + sourceToRead += 1; + if (sourceToRead >= numSources) { + return EndOfInput; + } + } + + // Here, we care about making negative valued characters positive + return sources[sourceToRead][charToRead]; + } + + // go back one character + void unget() + { + // Do not roll back once we've reached the end of the file. + if (endOfFileReached) + return; + + if (currentChar > 0) { + --currentChar; + --loc[currentSource].column; + --logicalSourceLoc.column; + if (loc[currentSource].column < 0) { + // We've moved back past a new line. Find the + // previous newline (or start of the file) to compute + // the column count on the now current line. + size_t chIndex = currentChar; + while (chIndex > 0) { + if (sources[currentSource][chIndex] == '\n') { + break; + } + --chIndex; + } + logicalSourceLoc.column = (int)(currentChar - chIndex); + loc[currentSource].column = (int)(currentChar - chIndex); + } + } else { + do { + --currentSource; + } while (currentSource > 0 && lengths[currentSource] == 0); + if (lengths[currentSource] == 0) { + // set to 0 if we've backed up to the start of an empty string + currentChar = 0; + } else + currentChar = lengths[currentSource] - 1; + } + if (peek() == '\n') { + --loc[currentSource].line; + --logicalSourceLoc.line; + } + } + + // for #line override + void setLine(int newLine) + { + logicalSourceLoc.line = newLine; + loc[getLastValidSourceIndex()].line = newLine; + } + + // for #line override in filename based parsing + void setFile(const char* filename) + { + TString* fn_tstr = NewPoolTString(filename); + logicalSourceLoc.name = fn_tstr; + loc[getLastValidSourceIndex()].name = fn_tstr; + } + + void setFile(const char* filename, int i) + { + TString* fn_tstr = NewPoolTString(filename); + if (i == getLastValidSourceIndex()) { + logicalSourceLoc.name = fn_tstr; + } + loc[i].name = fn_tstr; + } + + void setString(int newString) + { + logicalSourceLoc.string = newString; + loc[getLastValidSourceIndex()].string = newString; + logicalSourceLoc.name = nullptr; + loc[getLastValidSourceIndex()].name = nullptr; + } + + // for #include content indentation + void setColumn(int col) + { + logicalSourceLoc.column = col; + loc[getLastValidSourceIndex()].column = col; + } + + void setEndOfInput() + { + endOfFileReached = true; + currentSource = numSources; + } + + bool atEndOfInput() const { return endOfFileReached; } + + const TSourceLoc& getSourceLoc() const + { + if (singleLogical) { + return logicalSourceLoc; + } else { + return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; + } + } + // Returns the index (starting from 0) of the most recent valid source string we are reading from. + int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } + + void consumeWhiteSpace(bool& foundNonSpaceTab); + bool consumeComment(); + void consumeWhitespaceComment(bool& foundNonSpaceTab); + bool scanVersion(int& version, EProfile& profile, bool& notFirstToken); + +protected: + + // advance one character + void advance() + { + ++currentChar; + if (currentChar >= lengths[currentSource]) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + while (currentSource < numSources && lengths[currentSource] == 0) { + ++currentSource; + if (currentSource < numSources) { + loc[currentSource].string = loc[currentSource - 1].string + 1; + loc[currentSource].line = 1; + loc[currentSource].column = 0; + } + } + currentChar = 0; + } + } + + int numSources; // number of strings in source + const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput + const size_t *lengths; // length of each string + int currentSource; + size_t currentChar; + + // This is for reporting what string/line an error occurred on, and can be overridden by #line. + // It remembers the last state of each source string as it is left for the next one, so unget() + // can restore that state. + TSourceLoc* loc; // an array + + int stringBias; // the first string that is the user's string number 0 + int finale; // number of internal strings after user's last string + + TSourceLoc logicalSourceLoc; + bool singleLogical; // treats the strings as a single logical string. + // locations will be reported from the first string. + + // Set to true once peek() returns EndOfFile, so that we won't roll back + // once we've reached EndOfFile. + bool endOfFileReached; +}; + +} // end namespace glslang + +#endif // _GLSLANG_SCAN_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/ScanContext.h b/ios/include/glslang/MachineIndependent/ScanContext.h new file mode 100644 index 00000000..74b2b3c7 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/ScanContext.h @@ -0,0 +1,93 @@ +// +// Copyright (C) 2013 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. +// + +// +// This holds context specific to the GLSL scanner, which +// sits between the preprocessor scanner and parser. +// + +#pragma once + +#include "ParseHelper.h" + +namespace glslang { + +class TPpContext; +class TPpToken; +class TParserToken; + +class TScanContext { +public: + explicit TScanContext(TParseContextBase& pc) : + parseContext(pc), + afterType(false), afterStruct(false), + field(false), afterBuffer(false) { } + virtual ~TScanContext() { } + + static void fillInKeywordMap(); + static void deleteKeywordMap(); + + int tokenize(TPpContext*, TParserToken&); + +protected: + TScanContext(TScanContext&); + TScanContext& operator=(TScanContext&); + + int tokenizeIdentifier(); + int identifierOrType(); + int reservedWord(); + int identifierOrReserved(bool reserved); + int es30ReservedFromGLSL(int version); + int nonreservedKeyword(int esVersion, int nonEsVersion); + int precisionKeyword(); + int matNxM(); + int dMat(); + int firstGenerationImage(bool inEs310); + int secondGenerationImage(); + + TParseContextBase& parseContext; + bool afterType; // true if we've recognized a type, so can only be looking for an identifier + bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier + bool field; // true if we're on a field, right after a '.' + bool afterBuffer; // true if we've recognized the BUFFER keyword + TSourceLoc loc; + TParserToken* parserToken; + TPpToken* ppToken; + + const char* tokenText; + int keyword; +}; + +} // end namespace glslang diff --git a/ios/include/glslang/MachineIndependent/SymbolTable.h b/ios/include/glslang/MachineIndependent/SymbolTable.h new file mode 100644 index 00000000..40ca3da5 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/SymbolTable.h @@ -0,0 +1,885 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013 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. +// + +#ifndef _SYMBOL_TABLE_INCLUDED_ +#define _SYMBOL_TABLE_INCLUDED_ + +// +// Symbol table for parsing. Has these design characteristics: +// +// * Same symbol table can be used to compile many shaders, to preserve +// effort of creating and loading with the large numbers of built-in +// symbols. +// +// --> This requires a copy mechanism, so initial pools used to create +// the shared information can be popped. Done through "clone" +// methods. +// +// * Name mangling will be used to give each function a unique name +// so that symbol table lookups are never ambiguous. This allows +// a simpler symbol table structure. +// +// * Pushing and popping of scope, so symbol table will really be a stack +// of symbol tables. Searched from the top, with new inserts going into +// the top. +// +// * Constants: Compile time constant symbols will keep their values +// in the symbol table. The parser can substitute constants at parse +// time, including doing constant folding and constant propagation. +// +// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) +// are tracked in the intermediate representation, not the symbol table. +// + +#include "../Include/Common.h" +#include "../Include/intermediate.h" +#include "../Include/InfoSink.h" + +namespace glslang { + +// +// Symbol base class. (Can build functions or variables out of these...) +// + +class TVariable; +class TFunction; +class TAnonMember; + +typedef TVector TExtensionList; + +class TSymbol { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { } + virtual TSymbol* clone() const = 0; + virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool + + virtual const TString& getName() const { return *name; } + virtual void changeName(const TString* newName) { name = newName; } + virtual void addPrefix(const char* prefix) + { + TString newName(prefix); + newName.append(*name); + changeName(NewPoolTString(newName.c_str())); + } + virtual const TString& getMangledName() const { return getName(); } + virtual TFunction* getAsFunction() { return 0; } + virtual const TFunction* getAsFunction() const { return 0; } + virtual TVariable* getAsVariable() { return 0; } + virtual const TVariable* getAsVariable() const { return 0; } + virtual const TAnonMember* getAsAnonMember() const { return 0; } + virtual const TType& getType() const = 0; + virtual TType& getWritableType() = 0; + virtual void setUniqueId(int id) { uniqueId = id; } + virtual int getUniqueId() const { return uniqueId; } + virtual void setExtensions(int numExts, const char* const exts[]) + { + assert(extensions == 0); + assert(numExts > 0); + extensions = NewPoolObject(extensions); + for (int e = 0; e < numExts; ++e) + extensions->push_back(exts[e]); + } + virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } + virtual const char** getExtensions() const { return extensions->data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; + void dumpExtensions(TInfoSink& infoSink) const; +#endif + + virtual bool isReadOnly() const { return ! writable; } + virtual void makeReadOnly() { writable = false; } + +protected: + explicit TSymbol(const TSymbol&); + TSymbol& operator=(const TSymbol&); + + const TString *name; + unsigned int uniqueId; // For cross-scope comparing during code generation + + // For tracking what extensions must be present + // (don't use if correct version/profile is present). + TExtensionList* extensions; // an array of pointers to existing constant char strings + + // + // N.B.: Non-const functions that will be generally used should assert on this, + // to avoid overwriting shared symbol-table information. + // + bool writable; +}; + +// +// Variable class, meaning a symbol that's not a function. +// +// There could be a separate class hierarchy for Constant variables; +// Only one of int, bool, or float, (or none) is correct for +// any particular use, but it's easy to do this way, and doesn't +// seem worth having separate classes, and "getConst" can't simply return +// different values for different types polymorphically, so this is +// just simple and pragmatic. +// +class TVariable : public TSymbol { +public: + TVariable(const TString *name, const TType& t, bool uT = false ) + : TSymbol(name), + userType(uT), + constSubtree(nullptr), + memberExtensions(nullptr), + anonId(-1) + { type.shallowCopy(t); } + virtual TVariable* clone() const; + virtual ~TVariable() { } + + virtual TVariable* getAsVariable() { return this; } + virtual const TVariable* getAsVariable() const { return this; } + virtual const TType& getType() const { return type; } + virtual TType& getWritableType() { assert(writable); return type; } + virtual bool isUserType() const { return userType; } + virtual const TConstUnionArray& getConstArray() const { return constArray; } + virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } + virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } + virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } + virtual TIntermTyped* getConstSubtree() const { return constSubtree; } + virtual void setAnonId(int i) { anonId = i; } + virtual int getAnonId() const { return anonId; } + + virtual void setMemberExtensions(int member, int numExts, const char* const exts[]) + { + assert(type.isStruct()); + assert(numExts > 0); + if (memberExtensions == nullptr) { + memberExtensions = NewPoolObject(memberExtensions); + memberExtensions->resize(type.getStruct()->size()); + } + for (int e = 0; e < numExts; ++e) + (*memberExtensions)[member].push_back(exts[e]); + } + virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; } + virtual int getNumMemberExtensions(int member) const + { + return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size(); + } + virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + +protected: + explicit TVariable(const TVariable&); + TVariable& operator=(const TVariable&); + + TType type; + bool userType; + + // we are assuming that Pool Allocator will free the memory allocated to unionArray + // when this object is destroyed + + TConstUnionArray constArray; // for compile-time constant value + TIntermTyped* constSubtree; // for specialization constant computation + TVector* memberExtensions; // per-member extension list, allocated only when needed + int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose +}; + +// +// The function sub-class of symbols and the parser will need to +// share this definition of a function parameter. +// +struct TParameter { + TString *name; + TType* type; + TIntermTyped* defaultValue; + void copyParam(const TParameter& param) + { + if (param.name) + name = NewPoolTString(param.name->c_str()); + else + name = 0; + type = param.type->clone(); + defaultValue = param.defaultValue; + } + TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; } +}; + +// +// The function sub-class of a symbol. +// +class TFunction : public TSymbol { +public: + explicit TFunction(TOperator o) : + TSymbol(0), + op(o), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { } + TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) : + TSymbol(name), + mangledName(*name + '('), + op(tOp), + defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) + { + returnType.shallowCopy(retType); + declaredBuiltIn = retType.getQualifier().builtIn; + } + virtual TFunction* clone() const override; + virtual ~TFunction(); + + virtual TFunction* getAsFunction() override { return this; } + virtual const TFunction* getAsFunction() const override { return this; } + + // Install 'p' as the (non-'this') last parameter. + // Non-'this' parameters are reflected in both the list of parameters and the + // mangled name. + virtual void addParameter(TParameter& p) + { + assert(writable); + parameters.push_back(p); + p.type->appendMangledName(mangledName); + + if (p.defaultValue != nullptr) + defaultParamCount++; + } + + // Install 'this' as the first parameter. + // 'this' is reflected in the list of parameters, but not the mangled name. + virtual void addThisParameter(TType& type, const char* name) + { + TParameter p = { NewPoolTString(name), new TType, nullptr }; + p.type->shallowCopy(type); + parameters.insert(parameters.begin(), p); + } + + virtual void addPrefix(const char* prefix) override + { + TSymbol::addPrefix(prefix); + mangledName.insert(0, prefix); + } + + virtual void removePrefix(const TString& prefix) + { + assert(mangledName.compare(0, prefix.size(), prefix) == 0); + mangledName.erase(0, prefix.size()); + } + + virtual const TString& getMangledName() const override { return mangledName; } + virtual const TType& getType() const override { return returnType; } + virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; } + virtual TType& getWritableType() override { return returnType; } + virtual void relateToOperator(TOperator o) { assert(writable); op = o; } + virtual TOperator getBuiltInOp() const { return op; } + virtual void setDefined() { assert(writable); defined = true; } + virtual bool isDefined() const { return defined; } + virtual void setPrototyped() { assert(writable); prototyped = true; } + virtual bool isPrototyped() const { return prototyped; } + virtual void setImplicitThis() { assert(writable); implicitThis = true; } + virtual bool hasImplicitThis() const { return implicitThis; } + virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; } + virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; } + + // Return total number of parameters + virtual int getParamCount() const { return static_cast(parameters.size()); } + // Return number of parameters with default values. + virtual int getDefaultParamCount() const { return defaultParamCount; } + // Return number of fixed parameters (without default values) + virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); } + + virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; } + virtual const TParameter& operator[](int i) const { return parameters[i]; } + +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TFunction(const TFunction&); + TFunction& operator=(const TFunction&); + + typedef TVector TParamList; + TParamList parameters; + TType returnType; + TBuiltInVariable declaredBuiltIn; + + TString mangledName; + TOperator op; + bool defined; + bool prototyped; + bool implicitThis; // True if this function is allowed to see all members of 'this' + bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this', + // even if it finds member variables in the symbol table. + // This is important for a static member function that has member variables in scope, + // but is not allowed to use them, or see hidden symbols instead. + int defaultParamCount; +}; + +// +// Members of anonymous blocks are a kind of TSymbol. They are not hidden in +// the symbol table behind a container; rather they are visible and point to +// their anonymous container. (The anonymous container is found through the +// member, not the other way around.) +// +class TAnonMember : public TSymbol { +public: + TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } + virtual TAnonMember* clone() const override; + virtual ~TAnonMember() { } + + virtual const TAnonMember* getAsAnonMember() const override { return this; } + virtual const TVariable& getAnonContainer() const { return anonContainer; } + virtual unsigned int getMemberNumber() const { return memberNumber; } + + virtual const TType& getType() const override + { + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual TType& getWritableType() override + { + assert(writable); + const TTypeList& types = *anonContainer.getType().getStruct(); + return *types[memberNumber].type; + } + + virtual void setExtensions(int numExts, const char* const exts[]) override + { + anonContainer.setMemberExtensions(memberNumber, numExts, exts); + } + virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); } + virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } + + virtual int getAnonId() const { return anonId; } +#ifndef GLSLANG_WEB + virtual void dump(TInfoSink& infoSink, bool complete = false) const override; +#endif + +protected: + explicit TAnonMember(const TAnonMember&); + TAnonMember& operator=(const TAnonMember&); + + TVariable& anonContainer; + unsigned int memberNumber; + int anonId; +}; + +class TSymbolTableLevel { +public: + POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) + TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { } + ~TSymbolTableLevel(); + + bool insert(TSymbol& symbol, bool separateNameSpaces) + { + // + // returning true means symbol was added to the table with no semantic errors + // + const TString& name = symbol.getName(); + if (name == "") { + symbol.getAsVariable()->setAnonId(anonId++); + // An empty name means an anonymous container, exposing its members to the external scope. + // Give it a name and insert its members in the symbol table, pointing to the container. + char buf[20]; + snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId()); + symbol.changeName(NewPoolTString(buf)); + + return insertAnonymousMembers(symbol, 0); + } else { + // Check for redefinition errors: + // - STL itself will tell us if there is a direct name collision, with name mangling, at this level + // - additionally, check for function-redefining-variable name collisions + const TString& insertName = symbol.getMangledName(); + if (symbol.getAsFunction()) { + // make sure there isn't a variable of this name + if (! separateNameSpaces && level.find(name) != level.end()) + return false; + + // insert, and whatever happens is okay + level.insert(tLevelPair(insertName, &symbol)); + + return true; + } else + return level.insert(tLevelPair(insertName, &symbol)).second; + } + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + // Only supporting amend of anonymous blocks so far. + if (IsAnonymous(symbol.getName())) + return insertAnonymousMembers(symbol, firstNewMember); + else + return false; + } + + bool insertAnonymousMembers(TSymbol& symbol, int firstMember) + { + const TTypeList& types = *symbol.getAsVariable()->getType().getStruct(); + for (unsigned int m = firstMember; m < types.size(); ++m) { + TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId()); + if (! level.insert(tLevelPair(member->getMangledName(), member)).second) + return false; + } + + return true; + } + + TSymbol* find(const TString& name) const + { + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; + } + + void findFunctionNameList(const TString& name, TVector& list) + { + size_t parenAt = name.find_first_of('('); + TString base(name, 0, parenAt + 1); + + tLevel::const_iterator begin = level.lower_bound(base); + base[parenAt] = ')'; // assume ')' is lexically after '(' + tLevel::const_iterator end = level.upper_bound(base); + for (tLevel::const_iterator it = begin; it != end; ++it) + list.push_back(it->second->getAsFunction()); + } + + // See if there is already a function in the table having the given non-function-style name. + bool hasFunctionName(const TString& name) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) + + return true; + } + + return false; + } + + // See if there is a variable at this level having the given non-function-style name. + // Return true if name is found, and set variable to true if the name was a variable. + bool findFunctionVariableName(const TString& name, bool& variable) const + { + tLevel::const_iterator candidate = level.lower_bound(name); + if (candidate != level.end()) { + const TString& candidateName = (*candidate).first; + TString::size_type parenAt = candidateName.find_first_of('('); + if (parenAt == candidateName.npos) { + // not a mangled name + if (candidateName == name) { + // found a variable name match + variable = true; + return true; + } + } else { + // a mangled name + if (candidateName.compare(0, parenAt, name) == 0) { + // found a function name match + variable = false; + return true; + } + } + } + + return false; + } + + // Use this to do a lazy 'push' of precision defaults the first time + // a precision statement is seen in a new scope. Leave it at 0 for + // when no push was needed. Thus, it is not the current defaults, + // it is what to restore the defaults to when popping a level. + void setPreviousDefaultPrecisions(const TPrecisionQualifier *p) + { + // can call multiple times at one scope, will only latch on first call, + // as we're tracking the previous scope's values, not the current values + if (defaultPrecision != 0) + return; + + defaultPrecision = new TPrecisionQualifier[EbtNumTypes]; + for (int t = 0; t < EbtNumTypes; ++t) + defaultPrecision[t] = p[t]; + } + + void getPreviousDefaultPrecisions(TPrecisionQualifier *p) + { + // can be called for table level pops that didn't set the + // defaults + if (defaultPrecision == 0 || p == 0) + return; + + for (int t = 0; t < EbtNumTypes; ++t) + p[t] = defaultPrecision[t]; + } + + void relateToOperator(const char* name, TOperator op); + void setFunctionExtensions(const char* name, int num, const char* const extensions[]); +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + TSymbolTableLevel* clone() const; + void readOnly(); + + void setThisLevel() { thisLevel = true; } + bool isThisLevel() const { return thisLevel; } + +protected: + explicit TSymbolTableLevel(TSymbolTableLevel&); + TSymbolTableLevel& operator=(TSymbolTableLevel&); + + typedef std::map, pool_allocator > > tLevel; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; + + tLevel level; // named mappings + TPrecisionQualifier *defaultPrecision; + int anonId; + bool thisLevel; // True if this level of the symbol table is a structure scope containing member function + // that are supposed to see anonymous access to member variables. +}; + +class TSymbolTable { +public: + TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0) + { + // + // This symbol table cannot be used until push() is called. + // + } + ~TSymbolTable() + { + // this can be called explicitly; safest to code it so it can be called multiple times + + // don't deallocate levels passed in from elsewhere + while (table.size() > adoptedLevels) + pop(0); + } + + void adoptLevels(TSymbolTable& symTable) + { + for (unsigned int level = 0; level < symTable.table.size(); ++level) { + table.push_back(symTable.table[level]); + ++adoptedLevels; + } + uniqueId = symTable.uniqueId; + noBuiltInRedeclarations = symTable.noBuiltInRedeclarations; + separateNameSpaces = symTable.separateNameSpaces; + } + + // + // While level adopting is generic, the methods below enact a the following + // convention for levels: + // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables + // 1: per-stage built-ins, shared across all compiles, but a different copy per stage + // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins + // 3: user-shader globals + // +protected: + static const int globalLevel = 3; + bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels + bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals + bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals +public: + bool isEmpty() { return table.size() == 0; } + bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } + bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } + + void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } + void setSeparateNameSpaces() { separateNameSpaces = true; } + + void push() + { + table.push_back(new TSymbolTableLevel); + } + + // Make a new symbol-table level to represent the scope introduced by a structure + // containing member functions, such that the member functions can find anonymous + // references to member variables. + // + // 'thisSymbol' should have a name of "" to trigger anonymous structure-member + // symbol finds. + void pushThis(TSymbol& thisSymbol) + { + assert(thisSymbol.getName().size() == 0); + table.push_back(new TSymbolTableLevel); + table.back()->setThisLevel(); + insert(thisSymbol); + } + + void pop(TPrecisionQualifier *p) + { + table[currentLevel()]->getPreviousDefaultPrecisions(p); + delete table.back(); + table.pop_back(); + } + + // + // Insert a visible symbol into the symbol table so it can + // be found later by name. + // + // Returns false if the was a name collision. + // + bool insert(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + + // make sure there isn't a function of this variable name + if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName())) + return false; + + // check for not overloading or redefining a built-in function + if (noBuiltInRedeclarations) { + if (atGlobalLevel() && currentLevel() > 0) { + if (table[0]->hasFunctionName(symbol.getName())) + return false; + if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName())) + return false; + } + } + + return table[currentLevel()]->insert(symbol, separateNameSpaces); + } + + // Add more members to an already inserted aggregate object + bool amend(TSymbol& symbol, int firstNewMember) + { + // See insert() for comments on basic explanation of insert. + // This operates similarly, but more simply. + return table[currentLevel()]->amend(symbol, firstNewMember); + } + + // + // To allocate an internal temporary, which will need to be uniquely + // identified by the consumer of the AST, but never need to + // found by doing a symbol table search by name, hence allowed an + // arbitrary name in the symbol with no worry of collision. + // + void makeInternalVariable(TSymbol& symbol) + { + symbol.setUniqueId(++uniqueId); + } + + // + // Copy a variable or anonymous member's structure from a shared level so that + // it can be added (soon after return) to the symbol table where it can be + // modified without impacting other users of the shared table. + // + TSymbol* copyUpDeferredInsert(TSymbol* shared) + { + if (shared->getAsVariable()) { + TSymbol* copy = shared->clone(); + copy->setUniqueId(shared->getUniqueId()); + return copy; + } else { + const TAnonMember* anon = shared->getAsAnonMember(); + assert(anon); + TVariable* container = anon->getAnonContainer().clone(); + container->changeName(NewPoolTString("")); + container->setUniqueId(anon->getAnonContainer().getUniqueId()); + return container; + } + } + + TSymbol* copyUp(TSymbol* shared) + { + TSymbol* copy = copyUpDeferredInsert(shared); + table[globalLevel]->insert(*copy, separateNameSpaces); + if (shared->getAsVariable()) + return copy; + else { + // return the copy of the anonymous member + return table[globalLevel]->find(shared->getName()); + } + } + + // Normal find of a symbol, that can optionally say whether the symbol was found + // at a built-in level or the current top-scope level. + TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0) + { + int level = currentLevel(); + TSymbol* symbol; + int thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == nullptr && level >= 0); + level++; + if (builtIn) + *builtIn = isBuiltInLevel(level); + if (currentScope) + *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals + if (thisDepthP != nullptr) { + if (! table[level]->isThisLevel()) + thisDepth = 0; + *thisDepthP = thisDepth; + } + + return symbol; + } + + // Find of a symbol that returns how many layers deep of nested + // structures-with-member-functions ('this' scopes) deep the symbol was + // found in. + TSymbol* find(const TString& name, int& thisDepth) + { + int level = currentLevel(); + TSymbol* symbol; + thisDepth = 0; + do { + if (table[level]->isThisLevel()) + ++thisDepth; + symbol = table[level]->find(name); + --level; + } while (symbol == 0 && level >= 0); + + if (! table[level + 1]->isThisLevel()) + thisDepth = 0; + + return symbol; + } + + bool isFunctionNameVariable(const TString& name) const + { + if (separateNameSpaces) + return false; + + int level = currentLevel(); + do { + bool variable; + bool found = table[level]->findFunctionVariableName(name, variable); + if (found) + return variable; + --level; + } while (level >= 0); + + return false; + } + + void findFunctionNameList(const TString& name, TVector& list, bool& builtIn) + { + // For user levels, return the set found in the first scope with a match + builtIn = false; + int level = currentLevel(); + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (list.empty() && level >= globalLevel); + + if (! list.empty()) + return; + + // Gather across all built-in levels; they don't hide each other + builtIn = true; + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (level >= 0); + } + + void relateToOperator(const char* name, TOperator op) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->relateToOperator(name, op); + } + + void setFunctionExtensions(const char* name, int num, const char* const extensions[]) + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->setFunctionExtensions(name, num, extensions); + } + + void setVariableExtensions(const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(name)); + if (symbol == nullptr) + return; + + symbol->setExtensions(numExts, extensions); + } + + void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[]) + { + TSymbol* symbol = find(TString(blockName)); + if (symbol == nullptr) + return; + TVariable* variable = symbol->getAsVariable(); + assert(variable != nullptr); + + const TTypeList& structure = *variable->getAsVariable()->getType().getStruct(); + for (int member = 0; member < (int)structure.size(); ++member) { + if (structure[member].type->getFieldName().compare(name) == 0) { + variable->setMemberExtensions(member, numExts, extensions); + return; + } + } + } + + int getMaxSymbolId() { return uniqueId; } +#ifndef GLSLANG_WEB + void dump(TInfoSink& infoSink, bool complete = false) const; +#endif + void copyTable(const TSymbolTable& copyOf); + + void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } + + void readOnly() + { + for (unsigned int level = 0; level < table.size(); ++level) + table[level]->readOnly(); + } + +protected: + TSymbolTable(TSymbolTable&); + TSymbolTable& operator=(TSymbolTableLevel&); + + int currentLevel() const { return static_cast(table.size()) - 1; } + + std::vector table; + int uniqueId; // for unique identification in code generation + bool noBuiltInRedeclarations; + bool separateNameSpaces; + unsigned int adoptedLevels; +}; + +} // end namespace glslang + +#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/Versions.h b/ios/include/glslang/MachineIndependent/Versions.h new file mode 100644 index 00000000..98a88e1d --- /dev/null +++ b/ios/include/glslang/MachineIndependent/Versions.h @@ -0,0 +1,327 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2012-2013 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// 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. +// +#ifndef _VERSIONS_INCLUDED_ +#define _VERSIONS_INCLUDED_ + +#define LAST_ELEMENT_MARKER(x) x + +// +// Help manage multiple profiles, versions, extensions etc. +// + +// +// Profiles are set up for masking operations, so queries can be done on multiple +// profiles at the same time. +// +// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible +// defects from mixing the two different forms. +// +typedef enum { + EBadProfile = 0, + ENoProfile = (1 << 0), // only for desktop, before profiles showed up + ECoreProfile = (1 << 1), + ECompatibilityProfile = (1 << 2), + EEsProfile = (1 << 3), + LAST_ELEMENT_MARKER(EProfileCount), +} EProfile; + +namespace glslang { + +// +// Map from profile enum to externally readable text name. +// +inline const char* ProfileName(EProfile profile) +{ + switch (profile) { + case ENoProfile: return "none"; + case ECoreProfile: return "core"; + case ECompatibilityProfile: return "compatibility"; + case EEsProfile: return "es"; + default: return "unknown profile"; + } +} + +// +// What source rules, validation rules, target language, etc. are needed or +// desired for SPIR-V? +// +// 0 means a target or rule set is not enabled (ignore rules from that entity). +// Non-0 means to apply semantic rules arising from that version of its rule set. +// The union of all requested rule sets will be applied. +// +struct SpvVersion { + SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {} + unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header + int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX" + int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use + int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX" +}; + +// +// The behaviors from the GLSL "#extension extension_name : behavior" +// +typedef enum { + EBhMissing = 0, + EBhRequire, + EBhEnable, + EBhWarn, + EBhDisable, + EBhDisablePartial // use as initial state of an extension that is only partially implemented +} TExtensionBehavior; + +// +// Symbolic names for extensions. Strings may be directly used when calling the +// functions, but better to have the compiler do spelling checks. +// +const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D"; +const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives"; +const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth"; +const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; +const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3"; +const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target"; +const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod"; +const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers"; + +const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; +const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects"; +const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; +const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather"; +const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5"; +const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects"; +const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader"; +const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader"; +const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts"; +const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array"; +const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample"; +const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod"; +const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location"; +const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; +const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; +const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; +const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; +const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; +const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; +const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; +const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; +const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; +const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; +const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; +const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; +const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; +const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export"; +// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members +const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage"; +const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array"; +const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock"; +const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; +const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; +const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; +const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding"; +const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size"; +const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object"; +const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; +const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; + +const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; +const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; +const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic"; +const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot"; +const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle"; +const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; +const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; +const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; +const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics"; + +const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64"; + +const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers"; +const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted"; + +const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage"; +const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage"; + + +// EXT extensions +const char* const E_GL_EXT_device_group = "GL_EXT_device_group"; +const char* const E_GL_EXT_multiview = "GL_EXT_multiview"; +const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage"; +const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes"; +const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier"; +const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions"; +const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout"; +const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density"; +const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference"; +const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2"; +const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; +const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; +const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; +const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; +const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; +const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; +const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage }; +const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]); + +// OVR extensions +const char* const E_GL_OVR_multiview = "GL_OVR_multiview"; +const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2"; + +const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 }; +const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]); + +// #line and #include +const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive"; +const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive"; + +const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot"; +const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax"; +const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter"; +const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader"; +const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float"; +const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod"; +const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16"; +const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod"; +const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask"; +const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch"; + +const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2"; + +const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage"; +const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough"; +const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2"; +const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering"; +const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes"; +const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64"; +const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation"; +const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation"; +const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; +const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image"; +const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing"; +const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric"; +const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; +const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; +const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader"; + +// Arrays of extensions for the above viewportEXTs duplications + +const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 }; +const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]); + +const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; +const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; +const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; + +// AEP +const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a"; +const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced"; +const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables"; +const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic"; +const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation"; +const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array"; +const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader"; +const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size"; +const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5"; +const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box"; +const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks"; +const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader"; +const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; +const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer"; +const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array"; + +// OES matching AEP +const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; +const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size"; +const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5"; +const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box"; +const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks"; +const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader"; +const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size"; +const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer"; +const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array"; + +// EXT +const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32"; +const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64"; + +const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; +const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; +const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; + +// Arrays of extensions for the above AEP duplications + +const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader }; +const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]); + +const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size }; +const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]); + +const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 }; +const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]); + +const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box }; +const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]); + +const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks }; +const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]); + +const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader }; +const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]); + +const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size }; +const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]); + +const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer }; +const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]); + +const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array }; +const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]); + +} // end namespace glslang + +#endif // _VERSIONS_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/attribute.h b/ios/include/glslang/MachineIndependent/attribute.h new file mode 100644 index 00000000..38a943d2 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/attribute.h @@ -0,0 +1,149 @@ +// +// Copyright (C) 2017 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. +// + +#ifndef _ATTRIBUTE_INCLUDED_ +#define _ATTRIBUTE_INCLUDED_ + +#include "../Include/Common.h" +#include "../Include/ConstantUnion.h" + +namespace glslang { + + enum TAttributeType { + EatNone, + EatAllow_uav_condition, + EatBranch, + EatCall, + EatDomain, + EatEarlyDepthStencil, + EatFastOpt, + EatFlatten, + EatForceCase, + EatInstance, + EatMaxTessFactor, + EatNumThreads, + EatMaxVertexCount, + EatOutputControlPoints, + EatOutputTopology, + EatPartitioning, + EatPatchConstantFunc, + EatPatchSize, + EatUnroll, + EatLoop, + EatBinding, + EatGlobalBinding, + EatLocation, + EatInputAttachment, + EatBuiltIn, + EatPushConstant, + EatConstantId, + EatDependencyInfinite, + EatDependencyLength, + EatMinIterations, + EatMaxIterations, + EatIterationMultiple, + EatPeelCount, + EatPartialCount, + EatFormatRgba32f, + EatFormatRgba16f, + EatFormatR32f, + EatFormatRgba8, + EatFormatRgba8Snorm, + EatFormatRg32f, + EatFormatRg16f, + EatFormatR11fG11fB10f, + EatFormatR16f, + EatFormatRgba16, + EatFormatRgb10A2, + EatFormatRg16, + EatFormatRg8, + EatFormatR16, + EatFormatR8, + EatFormatRgba16Snorm, + EatFormatRg16Snorm, + EatFormatRg8Snorm, + EatFormatR16Snorm, + EatFormatR8Snorm, + EatFormatRgba32i, + EatFormatRgba16i, + EatFormatRgba8i, + EatFormatR32i, + EatFormatRg32i, + EatFormatRg16i, + EatFormatRg8i, + EatFormatR16i, + EatFormatR8i, + EatFormatRgba32ui, + EatFormatRgba16ui, + EatFormatRgba8ui, + EatFormatR32ui, + EatFormatRgb10a2ui, + EatFormatRg32ui, + EatFormatRg16ui, + EatFormatRg8ui, + EatFormatR16ui, + EatFormatR8ui, + EatFormatUnknown, + EatNonWritable, + EatNonReadable + }; + + class TIntermAggregate; + + struct TAttributeArgs { + TAttributeType name; + const TIntermAggregate* args; + + // Obtain attribute as integer + // Return false if it cannot be obtained + bool getInt(int& value, int argNum = 0) const; + + // Obtain attribute as string, with optional to-lower transform + // Return false if it cannot be obtained + bool getString(TString& value, int argNum = 0, bool convertToLower = true) const; + + // How many arguments were provided to the attribute? + int size() const; + + protected: + const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const; + }; + + typedef TList TAttributes; + +} // end namespace glslang + +#endif // _ATTRIBUTE_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/gl_types.h b/ios/include/glslang/MachineIndependent/gl_types.h new file mode 100644 index 00000000..b6f613bc --- /dev/null +++ b/ios/include/glslang/MachineIndependent/gl_types.h @@ -0,0 +1,210 @@ +/* +** Copyright (c) 2013 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. +** +** 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. +*/ + +#pragma once + +#define GL_FLOAT 0x1406 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 + +#define GL_DOUBLE 0x140A +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE + +#define GL_INT 0x1404 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 + +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 + +#define GL_INT64_ARB 0x140E +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB + +#define GL_UNSIGNED_INT64_ARB 0x140F +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7 + +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 + +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A + +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E + +// Those constants are borrowed from extension NV_gpu_shader5 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB + +#define GL_FLOAT16_MAT2_AMD 0x91C5 +#define GL_FLOAT16_MAT3_AMD 0x91C6 +#define GL_FLOAT16_MAT4_AMD 0x91C7 +#define GL_FLOAT16_MAT2x3_AMD 0x91C8 +#define GL_FLOAT16_MAT2x4_AMD 0x91C9 +#define GL_FLOAT16_MAT3x2_AMD 0x91CA +#define GL_FLOAT16_MAT3x4_AMD 0x91CB +#define GL_FLOAT16_MAT4x2_AMD 0x91CC +#define GL_FLOAT16_MAT4x3_AMD 0x91CD + +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D + +#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE +#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF +#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0 +#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1 +#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2 +#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3 +#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4 +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5 +#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7 +#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8 + +#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9 +#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA +#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB +#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC +#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD +#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE +#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF + +#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0 +#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1 +#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2 +#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3 +#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4 +#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5 +#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6 +#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7 +#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9 +#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA + +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E + +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A + +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C + +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB diff --git a/ios/include/glslang/MachineIndependent/glslang_tab.cpp.h b/ios/include/glslang/MachineIndependent/glslang_tab.cpp.h new file mode 100644 index 00000000..31c8f902 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/glslang_tab.cpp.h @@ -0,0 +1,521 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + CONST = 258, + BOOL = 259, + INT = 260, + UINT = 261, + FLOAT = 262, + BVEC2 = 263, + BVEC3 = 264, + BVEC4 = 265, + IVEC2 = 266, + IVEC3 = 267, + IVEC4 = 268, + UVEC2 = 269, + UVEC3 = 270, + UVEC4 = 271, + VEC2 = 272, + VEC3 = 273, + VEC4 = 274, + MAT2 = 275, + MAT3 = 276, + MAT4 = 277, + MAT2X2 = 278, + MAT2X3 = 279, + MAT2X4 = 280, + MAT3X2 = 281, + MAT3X3 = 282, + MAT3X4 = 283, + MAT4X2 = 284, + MAT4X3 = 285, + MAT4X4 = 286, + SAMPLER2D = 287, + SAMPLER3D = 288, + SAMPLERCUBE = 289, + SAMPLER2DSHADOW = 290, + SAMPLERCUBESHADOW = 291, + SAMPLER2DARRAY = 292, + SAMPLER2DARRAYSHADOW = 293, + ISAMPLER2D = 294, + ISAMPLER3D = 295, + ISAMPLERCUBE = 296, + ISAMPLER2DARRAY = 297, + USAMPLER2D = 298, + USAMPLER3D = 299, + USAMPLERCUBE = 300, + USAMPLER2DARRAY = 301, + SAMPLER = 302, + SAMPLERSHADOW = 303, + TEXTURE2D = 304, + TEXTURE3D = 305, + TEXTURECUBE = 306, + TEXTURE2DARRAY = 307, + ITEXTURE2D = 308, + ITEXTURE3D = 309, + ITEXTURECUBE = 310, + ITEXTURE2DARRAY = 311, + UTEXTURE2D = 312, + UTEXTURE3D = 313, + UTEXTURECUBE = 314, + UTEXTURE2DARRAY = 315, + ATTRIBUTE = 316, + VARYING = 317, + FLOAT16_T = 318, + FLOAT32_T = 319, + DOUBLE = 320, + FLOAT64_T = 321, + INT64_T = 322, + UINT64_T = 323, + INT32_T = 324, + UINT32_T = 325, + INT16_T = 326, + UINT16_T = 327, + INT8_T = 328, + UINT8_T = 329, + I64VEC2 = 330, + I64VEC3 = 331, + I64VEC4 = 332, + U64VEC2 = 333, + U64VEC3 = 334, + U64VEC4 = 335, + I32VEC2 = 336, + I32VEC3 = 337, + I32VEC4 = 338, + U32VEC2 = 339, + U32VEC3 = 340, + U32VEC4 = 341, + I16VEC2 = 342, + I16VEC3 = 343, + I16VEC4 = 344, + U16VEC2 = 345, + U16VEC3 = 346, + U16VEC4 = 347, + I8VEC2 = 348, + I8VEC3 = 349, + I8VEC4 = 350, + U8VEC2 = 351, + U8VEC3 = 352, + U8VEC4 = 353, + DVEC2 = 354, + DVEC3 = 355, + DVEC4 = 356, + DMAT2 = 357, + DMAT3 = 358, + DMAT4 = 359, + F16VEC2 = 360, + F16VEC3 = 361, + F16VEC4 = 362, + F16MAT2 = 363, + F16MAT3 = 364, + F16MAT4 = 365, + F32VEC2 = 366, + F32VEC3 = 367, + F32VEC4 = 368, + F32MAT2 = 369, + F32MAT3 = 370, + F32MAT4 = 371, + F64VEC2 = 372, + F64VEC3 = 373, + F64VEC4 = 374, + F64MAT2 = 375, + F64MAT3 = 376, + F64MAT4 = 377, + DMAT2X2 = 378, + DMAT2X3 = 379, + DMAT2X4 = 380, + DMAT3X2 = 381, + DMAT3X3 = 382, + DMAT3X4 = 383, + DMAT4X2 = 384, + DMAT4X3 = 385, + DMAT4X4 = 386, + F16MAT2X2 = 387, + F16MAT2X3 = 388, + F16MAT2X4 = 389, + F16MAT3X2 = 390, + F16MAT3X3 = 391, + F16MAT3X4 = 392, + F16MAT4X2 = 393, + F16MAT4X3 = 394, + F16MAT4X4 = 395, + F32MAT2X2 = 396, + F32MAT2X3 = 397, + F32MAT2X4 = 398, + F32MAT3X2 = 399, + F32MAT3X3 = 400, + F32MAT3X4 = 401, + F32MAT4X2 = 402, + F32MAT4X3 = 403, + F32MAT4X4 = 404, + F64MAT2X2 = 405, + F64MAT2X3 = 406, + F64MAT2X4 = 407, + F64MAT3X2 = 408, + F64MAT3X3 = 409, + F64MAT3X4 = 410, + F64MAT4X2 = 411, + F64MAT4X3 = 412, + F64MAT4X4 = 413, + ATOMIC_UINT = 414, + ACCSTRUCTNV = 415, + ACCSTRUCTEXT = 416, + RAYQUERYEXT = 417, + FCOOPMATNV = 418, + ICOOPMATNV = 419, + UCOOPMATNV = 420, + SAMPLERCUBEARRAY = 421, + SAMPLERCUBEARRAYSHADOW = 422, + ISAMPLERCUBEARRAY = 423, + USAMPLERCUBEARRAY = 424, + SAMPLER1D = 425, + SAMPLER1DARRAY = 426, + SAMPLER1DARRAYSHADOW = 427, + ISAMPLER1D = 428, + SAMPLER1DSHADOW = 429, + SAMPLER2DRECT = 430, + SAMPLER2DRECTSHADOW = 431, + ISAMPLER2DRECT = 432, + USAMPLER2DRECT = 433, + SAMPLERBUFFER = 434, + ISAMPLERBUFFER = 435, + USAMPLERBUFFER = 436, + SAMPLER2DMS = 437, + ISAMPLER2DMS = 438, + USAMPLER2DMS = 439, + SAMPLER2DMSARRAY = 440, + ISAMPLER2DMSARRAY = 441, + USAMPLER2DMSARRAY = 442, + SAMPLEREXTERNALOES = 443, + SAMPLEREXTERNAL2DY2YEXT = 444, + ISAMPLER1DARRAY = 445, + USAMPLER1D = 446, + USAMPLER1DARRAY = 447, + F16SAMPLER1D = 448, + F16SAMPLER2D = 449, + F16SAMPLER3D = 450, + F16SAMPLER2DRECT = 451, + F16SAMPLERCUBE = 452, + F16SAMPLER1DARRAY = 453, + F16SAMPLER2DARRAY = 454, + F16SAMPLERCUBEARRAY = 455, + F16SAMPLERBUFFER = 456, + F16SAMPLER2DMS = 457, + F16SAMPLER2DMSARRAY = 458, + F16SAMPLER1DSHADOW = 459, + F16SAMPLER2DSHADOW = 460, + F16SAMPLER1DARRAYSHADOW = 461, + F16SAMPLER2DARRAYSHADOW = 462, + F16SAMPLER2DRECTSHADOW = 463, + F16SAMPLERCUBESHADOW = 464, + F16SAMPLERCUBEARRAYSHADOW = 465, + IMAGE1D = 466, + IIMAGE1D = 467, + UIMAGE1D = 468, + IMAGE2D = 469, + IIMAGE2D = 470, + UIMAGE2D = 471, + IMAGE3D = 472, + IIMAGE3D = 473, + UIMAGE3D = 474, + IMAGE2DRECT = 475, + IIMAGE2DRECT = 476, + UIMAGE2DRECT = 477, + IMAGECUBE = 478, + IIMAGECUBE = 479, + UIMAGECUBE = 480, + IMAGEBUFFER = 481, + IIMAGEBUFFER = 482, + UIMAGEBUFFER = 483, + IMAGE1DARRAY = 484, + IIMAGE1DARRAY = 485, + UIMAGE1DARRAY = 486, + IMAGE2DARRAY = 487, + IIMAGE2DARRAY = 488, + UIMAGE2DARRAY = 489, + IMAGECUBEARRAY = 490, + IIMAGECUBEARRAY = 491, + UIMAGECUBEARRAY = 492, + IMAGE2DMS = 493, + IIMAGE2DMS = 494, + UIMAGE2DMS = 495, + IMAGE2DMSARRAY = 496, + IIMAGE2DMSARRAY = 497, + UIMAGE2DMSARRAY = 498, + F16IMAGE1D = 499, + F16IMAGE2D = 500, + F16IMAGE3D = 501, + F16IMAGE2DRECT = 502, + F16IMAGECUBE = 503, + F16IMAGE1DARRAY = 504, + F16IMAGE2DARRAY = 505, + F16IMAGECUBEARRAY = 506, + F16IMAGEBUFFER = 507, + F16IMAGE2DMS = 508, + F16IMAGE2DMSARRAY = 509, + TEXTURECUBEARRAY = 510, + ITEXTURECUBEARRAY = 511, + UTEXTURECUBEARRAY = 512, + TEXTURE1D = 513, + ITEXTURE1D = 514, + UTEXTURE1D = 515, + TEXTURE1DARRAY = 516, + ITEXTURE1DARRAY = 517, + UTEXTURE1DARRAY = 518, + TEXTURE2DRECT = 519, + ITEXTURE2DRECT = 520, + UTEXTURE2DRECT = 521, + TEXTUREBUFFER = 522, + ITEXTUREBUFFER = 523, + UTEXTUREBUFFER = 524, + TEXTURE2DMS = 525, + ITEXTURE2DMS = 526, + UTEXTURE2DMS = 527, + TEXTURE2DMSARRAY = 528, + ITEXTURE2DMSARRAY = 529, + UTEXTURE2DMSARRAY = 530, + F16TEXTURE1D = 531, + F16TEXTURE2D = 532, + F16TEXTURE3D = 533, + F16TEXTURE2DRECT = 534, + F16TEXTURECUBE = 535, + F16TEXTURE1DARRAY = 536, + F16TEXTURE2DARRAY = 537, + F16TEXTURECUBEARRAY = 538, + F16TEXTUREBUFFER = 539, + F16TEXTURE2DMS = 540, + F16TEXTURE2DMSARRAY = 541, + SUBPASSINPUT = 542, + SUBPASSINPUTMS = 543, + ISUBPASSINPUT = 544, + ISUBPASSINPUTMS = 545, + USUBPASSINPUT = 546, + USUBPASSINPUTMS = 547, + F16SUBPASSINPUT = 548, + F16SUBPASSINPUTMS = 549, + LEFT_OP = 550, + RIGHT_OP = 551, + INC_OP = 552, + DEC_OP = 553, + LE_OP = 554, + GE_OP = 555, + EQ_OP = 556, + NE_OP = 557, + AND_OP = 558, + OR_OP = 559, + XOR_OP = 560, + MUL_ASSIGN = 561, + DIV_ASSIGN = 562, + ADD_ASSIGN = 563, + MOD_ASSIGN = 564, + LEFT_ASSIGN = 565, + RIGHT_ASSIGN = 566, + AND_ASSIGN = 567, + XOR_ASSIGN = 568, + OR_ASSIGN = 569, + SUB_ASSIGN = 570, + STRING_LITERAL = 571, + LEFT_PAREN = 572, + RIGHT_PAREN = 573, + LEFT_BRACKET = 574, + RIGHT_BRACKET = 575, + LEFT_BRACE = 576, + RIGHT_BRACE = 577, + DOT = 578, + COMMA = 579, + COLON = 580, + EQUAL = 581, + SEMICOLON = 582, + BANG = 583, + DASH = 584, + TILDE = 585, + PLUS = 586, + STAR = 587, + SLASH = 588, + PERCENT = 589, + LEFT_ANGLE = 590, + RIGHT_ANGLE = 591, + VERTICAL_BAR = 592, + CARET = 593, + AMPERSAND = 594, + QUESTION = 595, + INVARIANT = 596, + HIGH_PRECISION = 597, + MEDIUM_PRECISION = 598, + LOW_PRECISION = 599, + PRECISION = 600, + PACKED = 601, + RESOURCE = 602, + SUPERP = 603, + FLOATCONSTANT = 604, + INTCONSTANT = 605, + UINTCONSTANT = 606, + BOOLCONSTANT = 607, + IDENTIFIER = 608, + TYPE_NAME = 609, + CENTROID = 610, + IN = 611, + OUT = 612, + INOUT = 613, + STRUCT = 614, + VOID = 615, + WHILE = 616, + BREAK = 617, + CONTINUE = 618, + DO = 619, + ELSE = 620, + FOR = 621, + IF = 622, + DISCARD = 623, + RETURN = 624, + SWITCH = 625, + CASE = 626, + DEFAULT = 627, + UNIFORM = 628, + SHARED = 629, + BUFFER = 630, + FLAT = 631, + SMOOTH = 632, + LAYOUT = 633, + DOUBLECONSTANT = 634, + INT16CONSTANT = 635, + UINT16CONSTANT = 636, + FLOAT16CONSTANT = 637, + INT32CONSTANT = 638, + UINT32CONSTANT = 639, + INT64CONSTANT = 640, + UINT64CONSTANT = 641, + SUBROUTINE = 642, + DEMOTE = 643, + PAYLOADNV = 644, + PAYLOADINNV = 645, + HITATTRNV = 646, + CALLDATANV = 647, + CALLDATAINNV = 648, + PAYLOADEXT = 649, + PAYLOADINEXT = 650, + HITATTREXT = 651, + CALLDATAEXT = 652, + CALLDATAINEXT = 653, + PATCH = 654, + SAMPLE = 655, + NONUNIFORM = 656, + COHERENT = 657, + VOLATILE = 658, + RESTRICT = 659, + READONLY = 660, + WRITEONLY = 661, + DEVICECOHERENT = 662, + QUEUEFAMILYCOHERENT = 663, + WORKGROUPCOHERENT = 664, + SUBGROUPCOHERENT = 665, + NONPRIVATE = 666, + SHADERCALLCOHERENT = 667, + NOPERSPECTIVE = 668, + EXPLICITINTERPAMD = 669, + PERVERTEXNV = 670, + PERPRIMITIVENV = 671, + PERVIEWNV = 672, + PERTASKNV = 673, + PRECISE = 674 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED + +union YYSTYPE +{ +#line 97 "glslang.y" /* yacc.c:1909 */ + + struct { + glslang::TSourceLoc loc; + union { + glslang::TString *string; + int i; + unsigned int u; + long long i64; + unsigned long long u64; + bool b; + double d; + }; + glslang::TSymbol* symbol; + } lex; + struct { + glslang::TSourceLoc loc; + glslang::TOperator op; + union { + TIntermNode* intermNode; + glslang::TIntermNodePair nodePair; + glslang::TIntermTyped* intermTypedNode; + glslang::TAttributes* attributes; + }; + union { + glslang::TPublicType type; + glslang::TFunction* function; + glslang::TParameter param; + glslang::TTypeLoc typeLine; + glslang::TTypeList* typeList; + glslang::TArraySizes* arraySizes; + glslang::TIdentifierList* identifierList; + }; + glslang::TArraySizes* typeParameters; + } interm; + +#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */ +}; + +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + + +int yyparse (glslang::TParseContext* pParseContext); + +#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/ios/include/glslang/MachineIndependent/iomapper.h b/ios/include/glslang/MachineIndependent/iomapper.h new file mode 100644 index 00000000..13a8932b --- /dev/null +++ b/ios/include/glslang/MachineIndependent/iomapper.h @@ -0,0 +1,300 @@ +// +// Copyright (C) 2016 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 GLSLANG_WEB + +#ifndef _IOMAPPER_INCLUDED +#define _IOMAPPER_INCLUDED + +#include +#include "LiveTraverser.h" +#include +#include +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +class TInfoSink; + +namespace glslang { + +class TIntermediate; +struct TVarEntryInfo { + int id; + TIntermSymbol* symbol; + bool live; + int newBinding; + int newSet; + int newLocation; + int newComponent; + int newIndex; + EShLanguage stage; + struct TOrderById { + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } + }; + + struct TOrderByPriority { + // ordering: + // 1) has both binding and set + // 2) has binding but no set + // 3) has no binding but set + // 4) has no binding and no set + inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { + const TQualifier& lq = l.symbol->getQualifier(); + const TQualifier& rq = r.symbol->getQualifier(); + + // simple rules: + // has binding gives 2 points + // has set gives 1 point + // who has the most points is more important. + int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); + int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); + + if (lPoints == rPoints) + return l.id < r.id; + return lPoints > rPoints; + } + }; +}; + +// Base class for shared TIoMapResolver services, used by several derivations. +struct TDefaultIoResolverBase : public glslang::TIoMapResolver { +public: + TDefaultIoResolverBase(const TIntermediate& intermediate); + typedef std::vector TSlotSet; + typedef std::unordered_map TSlotSetMap; + + // grow the reflection stage by stage + void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {} + void beginNotifications(EShLanguage) override {} + void endNotifications(EShLanguage) override {} + void beginResolve(EShLanguage) override {} + void endResolve(EShLanguage) override {} + void beginCollect(EShLanguage) override {} + void endCollect(EShLanguage) override {} + void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} + int getBaseBinding(TResourceType res, unsigned int set) const; + const std::vector& getResourceSetBinding() const; + virtual TResourceType getResourceType(const glslang::TType& type) = 0; + bool doAutoBindingMapping() const; + bool doAutoLocationMapping() const; + TSlotSet::iterator findSlot(int set, int slot); + bool checkEmpty(int set, int slot); + bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + int reserveSlot(int set, int slot, int size = 1); + int getFreeSlot(int set, int base, int size = 1); + int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void addStage(EShLanguage stage) override { + if (stage < EShLangCount) + stageMask[stage] = true; + } + uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); + + TSlotSetMap slots; + bool hasError = false; + +protected: + TDefaultIoResolverBase(TDefaultIoResolverBase&); + TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); + const TIntermediate& intermediate; + int nextUniformLocation; + int nextInputLocation; + int nextOutputLocation; + bool stageMask[EShLangCount + 1]; + // Return descriptor set specific base if there is one, and the generic base otherwise. + int selectBaseBinding(int base, int descriptorSetBase) const { + return descriptorSetBase != -1 ? descriptorSetBase : base; + } + + static int getLayoutSet(const glslang::TType& type) { + if (type.getQualifier().hasSet()) + return type.getQualifier().layoutSet; + else + return 0; + } + + static bool isSamplerType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler(); + } + + static bool isTextureType(const glslang::TType& type) { + return (type.getBasicType() == glslang::EbtSampler && + (type.getSampler().isTexture() || type.getSampler().isSubpass())); + } + + static bool isUboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqUniform; + } + + static bool isImageType(const glslang::TType& type) { + return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage(); + } + + static bool isSsboType(const glslang::TType& type) { + return type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a SRV (shader resource view) type: + static bool isSrvType(const glslang::TType& type) { + return isTextureType(type) || type.getQualifier().storage == EvqBuffer; + } + + // Return true if this is a UAV (unordered access view) type: + static bool isUavType(const glslang::TType& type) { + if (type.getQualifier().isReadOnly()) + return false; + return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || + (type.getQualifier().storage == EvqBuffer); + } +}; + +// Defaulf I/O resolver for OpenGL +struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { +public: + typedef std::map TVarSlotMap; // + typedef std::map TSlotMap; // + TDefaultGlslIoResolver(const TIntermediate& intermediate); + bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } + TResourceType getResourceType(const glslang::TType& type) override; + int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; + int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override; + void beginResolve(EShLanguage /*stage*/) override; + void endResolve(EShLanguage stage) override; + void beginCollect(EShLanguage) override; + void endCollect(EShLanguage) override; + void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; + // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol. + // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage. + // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key. + // Note: both stage and type must less then 0xffff. + int buildStorageKey(EShLanguage stage, TStorageQualifier type) { + assert(static_cast(stage) <= 0x0000ffff && static_cast(type) <= 0x0000ffff); + return (stage << 16) | type; + } + +protected: + // Use for mark pre stage, to get more interface symbol information. + EShLanguage preStage; + // Use for mark current shader stage for resolver + EShLanguage currentStage; + // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot + TSlotMap resourceSlotMap; + // Slot map for other resource(image, ubo, ssbo), It's a program share slot. + TSlotMap storageSlotMap; +}; + +typedef std::map TVarLiveMap; + +// override function "operator=", if a vector being sort, +// when use vc++, the sort function will call : +// pair& operator=(const pair<_Other1, _Other2>& _Right) +// { +// first = _Right.first; +// second = _Right.second; +// return (*this); +// } +// that will make a const type handing on left. +// override this function can avoid a compiler error. +// In the future, if the vc++ compiler can handle such a situation, +// this part of the code will be removed. +struct TVarLivePair : std::pair { + TVarLivePair(std::pair& _Right) : pair(_Right.first, _Right.second) {} + TVarLivePair& operator=(const TVarLivePair& _Right) { + const_cast(first) = _Right.first; + second = _Right.second; + return (*this); + } +}; +typedef std::vector TVarLiveVector; + +// I/O mapper +class TIoMapper { +public: + TIoMapper() {} + virtual ~TIoMapper() {} + // grow the reflection stage by stage + bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*); + bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } +}; + +// I/O mapper for OpenGL +class TGlslIoMapper : public TIoMapper { +public: + TGlslIoMapper() { + memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount); + memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount); + } + virtual ~TGlslIoMapper() { + for (size_t stage = 0; stage < EShLangCount; stage++) { + if (inVarMaps[stage] != nullptr) { + delete inVarMaps[stage]; + inVarMaps[stage] = nullptr; + } + if (outVarMaps[stage] != nullptr) { + delete outVarMaps[stage]; + outVarMaps[stage] = nullptr; + } + if (uniformVarMap[stage] != nullptr) { + delete uniformVarMap[stage]; + uniformVarMap[stage] = nullptr; + } + if (intermediates[stage] != nullptr) + intermediates[stage] = nullptr; + } + } + // grow the reflection stage by stage + bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; + bool doMap(TIoMapResolver*, TInfoSink&) override; + TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], + *uniformVarMap[EShLangCount]; + TIntermediate* intermediates[EShLangCount]; + bool hadError = false; +}; + +} // end namespace glslang + +#endif // _IOMAPPER_INCLUDED + +#endif // GLSLANG_WEB diff --git a/ios/include/glslang/MachineIndependent/localintermediate.h b/ios/include/glslang/MachineIndependent/localintermediate.h new file mode 100644 index 00000000..66f5a88a --- /dev/null +++ b/ios/include/glslang/MachineIndependent/localintermediate.h @@ -0,0 +1,1013 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2016 LunarG, Inc. +// Copyright (C) 2017 ARM Limited. +// 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. +// + +#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ +#define _LOCAL_INTERMEDIATE_INCLUDED_ + +#include "../Include/intermediate.h" +#include "../Public/ShaderLang.h" +#include "Versions.h" + +#include +#include +#include +#include +#include + +class TInfoSink; + +namespace glslang { + +struct TMatrixSelector { + int coord1; // stay agnostic about column/row; this is parse order + int coord2; +}; + +typedef int TVectorSelector; + +const int MaxSwizzleSelectors = 4; + +template +class TSwizzleSelectors { +public: + TSwizzleSelectors() : size_(0) { } + + void push_back(selectorType comp) + { + if (size_ < MaxSwizzleSelectors) + components[size_++] = comp; + } + void resize(int s) + { + assert(s <= size_); + size_ = s; + } + int size() const { return size_; } + selectorType operator[](int i) const + { + assert(i < MaxSwizzleSelectors); + return components[i]; + } + +private: + int size_; + selectorType components[MaxSwizzleSelectors]; +}; + +// +// Some helper structures for TIntermediate. Their contents are encapsulated +// by TIntermediate. +// + +// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies. +// A "call" is a pair: . +// There can be duplicates. General assumption is the list is small. +struct TCall { + TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { } + TString caller; + TString callee; + bool visited; + bool currentPath; + bool errorGiven; + int calleeBodyPosition; +}; + +// A generic 1-D range. +struct TRange { + TRange(int start, int last) : start(start), last(last) { } + bool overlap(const TRange& rhs) const + { + return last >= rhs.start && start <= rhs.last; + } + int start; + int last; +}; + +// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying +// within the same location range, component range, and index value. Locations don't alias unless +// all other dimensions of their range overlap. +struct TIoRange { + TIoRange(TRange location, TRange component, TBasicType basicType, int index) + : location(location), component(component), basicType(basicType), index(index) { } + bool overlap(const TIoRange& rhs) const + { + return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; + } + TRange location; + TRange component; + TBasicType basicType; + int index; +}; + +// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying +// within the same binding and offset range. +struct TOffsetRange { + TOffsetRange(TRange binding, TRange offset) + : binding(binding), offset(offset) { } + bool overlap(const TOffsetRange& rhs) const + { + return binding.overlap(rhs.binding) && offset.overlap(rhs.offset); + } + TRange binding; + TRange offset; +}; + +#ifndef GLSLANG_WEB +// Things that need to be tracked per xfb buffer. +struct TXfbBuffer { + TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false), + contains32BitType(false), contains16BitType(false) { } + std::vector ranges; // byte offsets that have already been assigned + unsigned int stride; + unsigned int implicitStride; + bool contains64BitType; + bool contains32BitType; + bool contains16BitType; +}; +#endif + +// Track a set of strings describing how the module was processed. +// This includes command line options, transforms, etc., ideally inclusive enough +// to reproduce the steps used to transform the input source to the output. +// E.g., see SPIR-V OpModuleProcessed. +// Each "process" or "transform" uses is expressed in the form: +// process arg0 arg1 arg2 ... +// process arg0 arg1 arg2 ... +// where everything is textual, and there can be zero or more arguments +class TProcesses { +public: + TProcesses() {} + ~TProcesses() {} + + void addProcess(const char* process) + { + processes.push_back(process); + } + void addProcess(const std::string& process) + { + processes.push_back(process); + } + void addArgument(int arg) + { + processes.back().append(" "); + std::string argString = std::to_string(arg); + processes.back().append(argString); + } + void addArgument(const char* arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addArgument(const std::string& arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addIfNonZero(const char* process, int value) + { + if (value != 0) { + addProcess(process); + addArgument(value); + } + } + + const std::vector& getProcesses() const { return processes; } + +private: + std::vector processes; +}; + +class TSymbolTable; +class TSymbol; +class TVariable; + +// +// Texture and Sampler transformation mode. +// +enum ComputeDerivativeMode { + LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled + LayoutDerivativeGroupQuads, // derivative_group_quadsNV + LayoutDerivativeGroupLinear, // derivative_group_linearNV +}; + +class TIdMaps { +public: + TMap& operator[](int i) { return maps[i]; } + const TMap& operator[](int i) const { return maps[i]; } +private: + TMap maps[EsiCount]; +}; + + +// +// Set of helper functions to help parse and build the tree. +// +class TIntermediate { +public: + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : + language(l), + profile(p), version(v), treeRoot(0), + numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), + invertY(false), + useStorageBuffer(false), + nanMinMaxClamp(false), + depthReplacing(false) +#ifndef GLSLANG_WEB + , + implicitThisName("@this"), implicitCounterName("@count"), + source(EShSourceNone), + useVulkanMemoryModel(false), + invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), + inputPrimitive(ElgNone), outputPrimitive(ElgNone), + pixelCenterInteger(false), originUpperLeft(false), + vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), + postDepthCoverage(false), depthLayout(EldNone), + hlslFunctionality1(false), + blendEquations(0), xfbMode(false), multiStream(false), + layoutOverrideCoverage(false), + geoPassthroughEXT(false), + numShaderRecordBlocks(0), + computeDerivativeMode(LayoutDerivativeNone), + primitives(TQualifier::layoutNotSet), + numTaskNVBlocks(0), + autoMapBindings(false), + autoMapLocations(false), + flattenUniformArrays(false), + useUnknownFormat(false), + hlslOffsets(false), + hlslIoMapping(false), + useVariablePointers(false), + textureSamplerTransformMode(EShTexSampTransKeep), + needToLegalize(false), + binaryDoubleOutput(false), + usePhysicalStorageBuffer(false), + uniformLocationBase(0) +#endif + { + localSize[0] = 1; + localSize[1] = 1; + localSize[2] = 1; + localSizeNotDefault[0] = false; + localSizeNotDefault[1] = false; + localSizeNotDefault[2] = false; + localSizeSpecId[0] = TQualifier::layoutNotSet; + localSizeSpecId[1] = TQualifier::layoutNotSet; + localSizeSpecId[2] = TQualifier::layoutNotSet; +#ifndef GLSLANG_WEB + xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); + shiftBinding.fill(0); +#endif + } + + void setVersion(int v) { version = v; } + int getVersion() const { return version; } + void setProfile(EProfile p) { profile = p; } + EProfile getProfile() const { return profile; } + void setSpv(const SpvVersion& s) + { + spvVersion = s; + + // client processes + if (spvVersion.vulkan > 0) + processes.addProcess("client vulkan100"); + if (spvVersion.openGl > 0) + processes.addProcess("client opengl100"); + + // target SPV + switch (spvVersion.spv) { + case 0: + break; + case EShTargetSpv_1_0: + break; + case EShTargetSpv_1_1: + processes.addProcess("target-env spirv1.1"); + break; + case EShTargetSpv_1_2: + processes.addProcess("target-env spirv1.2"); + break; + case EShTargetSpv_1_3: + processes.addProcess("target-env spirv1.3"); + break; + case EShTargetSpv_1_4: + processes.addProcess("target-env spirv1.4"); + break; + case EShTargetSpv_1_5: + processes.addProcess("target-env spirv1.5"); + break; + default: + processes.addProcess("target-env spirvUnknown"); + break; + } + + // target-environment processes + switch (spvVersion.vulkan) { + case 0: + break; + case EShTargetVulkan_1_0: + processes.addProcess("target-env vulkan1.0"); + break; + case EShTargetVulkan_1_1: + processes.addProcess("target-env vulkan1.1"); + break; + case EShTargetVulkan_1_2: + processes.addProcess("target-env vulkan1.2"); + break; + default: + processes.addProcess("target-env vulkanUnknown"); + break; + } + if (spvVersion.openGl > 0) + processes.addProcess("target-env opengl"); + } + const SpvVersion& getSpv() const { return spvVersion; } + EShLanguage getStage() const { return language; } + void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } + const std::set& getRequestedExtensions() const { return requestedExtensions; } + + void setTreeRoot(TIntermNode* r) { treeRoot = r; } + TIntermNode* getTreeRoot() const { return treeRoot; } + void incrementEntryPointCount() { ++numEntryPoints; } + int getNumEntryPoints() const { return numEntryPoints; } + int getNumErrors() const { return numErrors; } + void addPushConstantCount() { ++numPushConstants; } + void setLimits(const TBuiltInResource& r) { resources = r; } + + bool postProcess(TIntermNode*, EShLanguage); + void removeTree(); + + void setEntryPointName(const char* ep) + { + entryPointName = ep; + processes.addProcess("entry-point"); + processes.addArgument(entryPointName); + } + void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } + const std::string& getEntryPointName() const { return entryPointName; } + const std::string& getEntryPointMangledName() const { return entryPointMangledName; } + + void setInvertY(bool invert) + { + invertY = invert; + if (invertY) + processes.addProcess("invert-y"); + } + bool getInvertY() const { return invertY; } + +#ifdef ENABLE_HLSL + void setSource(EShSource s) { source = s; } + EShSource getSource() const { return source; } +#else + void setSource(EShSource s) { assert(s == EShSourceGlsl); } + EShSource getSource() const { return EShSourceGlsl; } +#endif + + bool isRecursive() const { return recursive; } + + TIntermSymbol* addSymbol(const TVariable&); + TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); + TIntermSymbol* addSymbol(const TIntermSymbol&); + TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); + std::tuple addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); + TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); + TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; + void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); + TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); + TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); + TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); + TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc); + TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); + bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; + bool isIntegralPromotion(TBasicType from, TBasicType to) const; + bool isFPPromotion(TBasicType from, TBasicType to) const; + bool isIntegralConversion(TBasicType from, TBasicType to) const; + bool isFPConversion(TBasicType from, TBasicType to) const; + bool isFPIntegralConversion(TBasicType from, TBasicType to) const; + TOperator mapTypeToConstructorOp(const TType&) const; + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); + TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); + TIntermAggregate* makeAggregate(TIntermNode* node); + TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); + TIntermAggregate* makeAggregate(const TSourceLoc&); + TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); + bool areAllChildConst(TIntermAggregate* aggrNode); + TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); + TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); + TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); + TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); + TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; + TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; + TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; + bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); + TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); + TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, + const TSourceLoc&, TIntermLoop*&); + TIntermBranch* addBranch(TOperator, const TSourceLoc&); + TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); + template TIntermTyped* addSwizzle(TSwizzleSelectors&, const TSourceLoc&); + + // Low level functions to add nodes (no conversions or other higher level transformations) + // If a type is provided, the node's type will be set to it. + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const; + TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const; + TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const; + + // Constant folding (in Constant.cpp) + TIntermTyped* fold(TIntermAggregate* aggrNode); + TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); + TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); + TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); + + // Tree ops + static const TIntermTyped* findLValueBase(const TIntermTyped*, bool swizzleOkay); + + // Linkage related + void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); + + void setUseStorageBuffer() + { + useStorageBuffer = true; + processes.addProcess("use-storage-buffer"); + } + bool usingStorageBuffer() const { return useStorageBuffer; } + void setDepthReplacing() { depthReplacing = true; } + bool isDepthReplacing() const { return depthReplacing; } + bool setLocalSize(int dim, int size) + { + if (localSizeNotDefault[dim]) + return size == localSize[dim]; + localSizeNotDefault[dim] = true; + localSize[dim] = size; + return true; + } + unsigned int getLocalSize(int dim) const { return localSize[dim]; } + bool setLocalSizeSpecId(int dim, int id) + { + if (localSizeSpecId[dim] != TQualifier::layoutNotSet) + return id == localSizeSpecId[dim]; + localSizeSpecId[dim] = id; + return true; + } + int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } +#ifdef GLSLANG_WEB + void output(TInfoSink&, bool tree) { } + + bool isEsProfile() const { return false; } + bool getXfbMode() const { return false; } + bool isMultiStream() const { return false; } + TLayoutGeometry getOutputPrimitive() const { return ElgNone; } + bool getPostDepthCoverage() const { return false; } + bool getEarlyFragmentTests() const { return false; } + TLayoutDepth getDepth() const { return EldNone; } + bool getPixelCenterInteger() const { return false; } + void setOriginUpperLeft() { } + bool getOriginUpperLeft() const { return true; } + TInterlockOrdering getInterlockOrdering() const { return EioNone; } + + bool getAutoMapBindings() const { return false; } + bool getAutoMapLocations() const { return false; } + int getNumPushConstants() const { return 0; } + void addShaderRecordCount() { } + void addTaskNVCount() { } + void setUseVulkanMemoryModel() { } + bool usingVulkanMemoryModel() const { return false; } + bool usingPhysicalStorageBuffer() const { return false; } + bool usingVariablePointers() const { return false; } + unsigned getXfbStride(int buffer) const { return 0; } + bool hasLayoutDerivativeModeNone() const { return false; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return LayoutDerivativeNone; } +#else + void output(TInfoSink&, bool tree); + + bool isEsProfile() const { return profile == EEsProfile; } + + void setShiftBinding(TResourceType res, unsigned int shift) + { + shiftBinding[res] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) + processes.addIfNonZero(name, shift); + } + + unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } + + void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) + { + if (shift == 0) // ignore if there's no shift: it's a no-op. + return; + + shiftBindingForSet[res][set] = shift; + + const char* name = getResourceName(res); + if (name != nullptr) { + processes.addProcess(name); + processes.addArgument(shift); + processes.addArgument(set); + } + } + + int getShiftBindingForSet(TResourceType res, unsigned int set) const + { + const auto shift = shiftBindingForSet[res].find(set); + return shift == shiftBindingForSet[res].end() ? -1 : shift->second; + } + bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } + + void setResourceSetBinding(const std::vector& shift) + { + resourceSetBinding = shift; + if (shift.size() > 0) { + processes.addProcess("resource-set-binding"); + for (int s = 0; s < (int)shift.size(); ++s) + processes.addArgument(shift[s]); + } + } + const std::vector& getResourceSetBinding() const { return resourceSetBinding; } + void setAutoMapBindings(bool map) + { + autoMapBindings = map; + if (autoMapBindings) + processes.addProcess("auto-map-bindings"); + } + bool getAutoMapBindings() const { return autoMapBindings; } + void setAutoMapLocations(bool map) + { + autoMapLocations = map; + if (autoMapLocations) + processes.addProcess("auto-map-locations"); + } + bool getAutoMapLocations() const { return autoMapLocations; } + +#ifdef ENABLE_HLSL + void setFlattenUniformArrays(bool flatten) + { + flattenUniformArrays = flatten; + if (flattenUniformArrays) + processes.addProcess("flatten-uniform-arrays"); + } + bool getFlattenUniformArrays() const { return flattenUniformArrays; } +#endif + void setNoStorageFormat(bool b) + { + useUnknownFormat = b; + if (useUnknownFormat) + processes.addProcess("no-storage-format"); + } + bool getNoStorageFormat() const { return useUnknownFormat; } + void setUseVulkanMemoryModel() + { + useVulkanMemoryModel = true; + processes.addProcess("use-vulkan-memory-model"); + } + bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } + void setUsePhysicalStorageBuffer() + { + usePhysicalStorageBuffer = true; + } + bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } + void setUseVariablePointers() + { + useVariablePointers = true; + processes.addProcess("use-variable-pointers"); + } + bool usingVariablePointers() const { return useVariablePointers; } + +#ifdef ENABLE_HLSL + template T addCounterBufferName(const T& name) const { return name + implicitCounterName; } + bool hasCounterBufferName(const TString& name) const { + size_t len = strlen(implicitCounterName); + return name.size() > len && + name.compare(name.size() - len, len, implicitCounterName) == 0; + } +#endif + + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } + int getNumPushConstants() const { return numPushConstants; } + void addShaderRecordCount() { ++numShaderRecordBlocks; } + void addTaskNVCount() { ++numTaskNVBlocks; } + + bool setInvocations(int i) + { + if (invocations != TQualifier::layoutNotSet) + return invocations == i; + invocations = i; + return true; + } + int getInvocations() const { return invocations; } + bool setVertices(int m) + { + if (vertices != TQualifier::layoutNotSet) + return vertices == m; + vertices = m; + return true; + } + int getVertices() const { return vertices; } + bool setInputPrimitive(TLayoutGeometry p) + { + if (inputPrimitive != ElgNone) + return inputPrimitive == p; + inputPrimitive = p; + return true; + } + TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } + bool setVertexSpacing(TVertexSpacing s) + { + if (vertexSpacing != EvsNone) + return vertexSpacing == s; + vertexSpacing = s; + return true; + } + TVertexSpacing getVertexSpacing() const { return vertexSpacing; } + bool setVertexOrder(TVertexOrder o) + { + if (vertexOrder != EvoNone) + return vertexOrder == o; + vertexOrder = o; + return true; + } + TVertexOrder getVertexOrder() const { return vertexOrder; } + void setPointMode() { pointMode = true; } + bool getPointMode() const { return pointMode; } + + bool setInterlockOrdering(TInterlockOrdering o) + { + if (interlockOrdering != EioNone) + return interlockOrdering == o; + interlockOrdering = o; + return true; + } + TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } + + void setXfbMode() { xfbMode = true; } + bool getXfbMode() const { return xfbMode; } + void setMultiStream() { multiStream = true; } + bool isMultiStream() const { return multiStream; } + bool setOutputPrimitive(TLayoutGeometry p) + { + if (outputPrimitive != ElgNone) + return outputPrimitive == p; + outputPrimitive = p; + return true; + } + TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } + void setPostDepthCoverage() { postDepthCoverage = true; } + bool getPostDepthCoverage() const { return postDepthCoverage; } + void setEarlyFragmentTests() { earlyFragmentTests = true; } + bool getEarlyFragmentTests() const { return earlyFragmentTests; } + bool setDepth(TLayoutDepth d) + { + if (depthLayout != EldNone) + return depthLayout == d; + depthLayout = d; + return true; + } + TLayoutDepth getDepth() const { return depthLayout; } + void setOriginUpperLeft() { originUpperLeft = true; } + bool getOriginUpperLeft() const { return originUpperLeft; } + void setPixelCenterInteger() { pixelCenterInteger = true; } + bool getPixelCenterInteger() const { return pixelCenterInteger; } + void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } + unsigned int getBlendEquations() const { return blendEquations; } + bool setXfbBufferStride(int buffer, unsigned stride) + { + if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) + return xfbBuffers[buffer].stride == stride; + xfbBuffers[buffer].stride = stride; + return true; + } + unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } + int addXfbBufferOffset(const TType&); + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; + unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; + void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } + bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } + void setGeoPassthroughEXT() { geoPassthroughEXT = true; } + bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } + void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } + bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } + ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } + bool setPrimitives(int m) + { + if (primitives != TQualifier::layoutNotSet) + return primitives == m; + primitives = m; + return true; + } + int getPrimitives() const { return primitives; } + const char* addSemanticName(const TString& name) + { + return semanticNameSet.insert(name).first->c_str(); + } + void addUniformLocationOverride(const char* nameStr, int location) + { + std::string name = nameStr; + uniformLocationOverrides[name] = location; + } + + int getUniformLocationOverride(const char* nameStr) const + { + std::string name = nameStr; + auto pos = uniformLocationOverrides.find(name); + if (pos == uniformLocationOverrides.end()) + return -1; + else + return pos->second; + } + + void setUniformLocationBase(int base) { uniformLocationBase = base; } + int getUniformLocationBase() const { return uniformLocationBase; } + + void setNeedsLegalization() { needToLegalize = true; } + bool needsLegalization() const { return needToLegalize; } + + void setBinaryDoubleOutput() { binaryDoubleOutput = true; } + bool getBinaryDoubleOutput() { return binaryDoubleOutput; } +#endif // GLSLANG_WEB + +#ifdef ENABLE_HLSL + void setHlslFunctionality1() { hlslFunctionality1 = true; } + bool getHlslFunctionality1() const { return hlslFunctionality1; } + void setHlslOffsets() + { + hlslOffsets = true; + if (hlslOffsets) + processes.addProcess("hlsl-offsets"); + } + bool usingHlslOffsets() const { return hlslOffsets; } + void setHlslIoMapping(bool b) + { + hlslIoMapping = b; + if (hlslIoMapping) + processes.addProcess("hlsl-iomap"); + } + bool usingHlslIoMapping() { return hlslIoMapping; } +#else + bool getHlslFunctionality1() const { return false; } + bool usingHlslOffsets() const { return false; } + bool usingHlslIoMapping() { return false; } +#endif + + void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); + void merge(TInfoSink&, TIntermediate&); + void finalCheck(TInfoSink&, bool keepUncalled); + + bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; + TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; + + void addIoAccessed(const TString& name) { ioAccessed.insert(name); } + bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } + + int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); + int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); + int addUsedOffsets(int binding, int offset, int numOffsets); + bool addUsedConstantId(int id); + static int computeTypeLocationSize(const TType&, EShLanguage); + static int computeTypeUniformLocationSize(const TType&); + + static int getBaseAlignmentScalar(const TType&, int& size); + static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); + static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); + static bool improperStraddle(const TType& type, int size, int offset); + static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); + static int getOffset(const TType& type, int index); + static int getBlockSize(const TType& blockType); + static int computeBufferReferenceTypeSize(const TType&); + bool promote(TIntermOperator*); + void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } + bool getNanMinMaxClamp() const { return nanMinMaxClamp; } + + void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } + const std::string& getSourceFile() const { return sourceFile; } + void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } + const std::string& getSourceText() const { return sourceText; } + const std::map& getIncludeText() const { return includeText; } + void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } + void addProcesses(const std::vector& p) + { + for (int i = 0; i < (int)p.size(); ++i) + processes.addProcess(p[i]); + } + void addProcess(const std::string& process) { processes.addProcess(process); } + void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } + const std::vector& getProcesses() const { return processes.getProcesses(); } + + // Certain explicit conversions are allowed conditionally +#ifdef GLSLANG_WEB + bool getArithemeticInt8Enabled() const { return false; } + bool getArithemeticInt16Enabled() const { return false; } + bool getArithemeticFloat16Enabled() const { return false; } +#else + bool getArithemeticInt8Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8); + } + bool getArithemeticInt16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_int16) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16); + } + + bool getArithemeticFloat16Enabled() const { + return extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || + extensionRequested(E_GL_AMD_gpu_shader_half_float) || + extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16); + } +#endif + +protected: + TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); + void error(TInfoSink& infoSink, const char*); + void warn(TInfoSink& infoSink, const char*); + void mergeCallGraphs(TInfoSink&, TIntermediate&); + void mergeModes(TInfoSink&, TIntermediate&); + void mergeTrees(TInfoSink&, TIntermediate&); + void seedIdMap(TIdMaps& idMaps, int& maxId); + void remapIds(const TIdMaps& idMaps, int idShift, TIntermediate&); + void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); + void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); + void mergeImplicitArraySizes(TType&, const TType&); + void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); + void checkCallGraphCycles(TInfoSink&); + void checkCallGraphBodies(TInfoSink&, bool keepUncalled); + void inOutLocationCheck(TInfoSink&); + TIntermAggregate* findLinkerObjects() const; + bool userOutputUsed() const; + bool isSpecializationOperation(const TIntermOperator&) const; + bool isNonuniformPropagating(TOperator) const; + bool promoteUnary(TIntermUnary&); + bool promoteBinary(TIntermBinary&); + void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); + bool promoteAggregate(TIntermAggregate&); + void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); + void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); + bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); + void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); + bool isConversionAllowed(TOperator op, TIntermTyped* node) const; + std::tuple getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; + + // JohnK: I think this function should go away. + // This data structure is just a log to pass on to back ends. + // Versioning and extensions are handled in Version.cpp, with a rich + // set of functions for querying stages, versions, extension enable/disabled, etc. +#ifdef GLSLANG_WEB + bool extensionRequested(const char *extension) const { return false; } +#else + bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} +#endif + + static const char* getResourceName(TResourceType); + + const EShLanguage language; // stage, known at construction time + std::string entryPointName; + std::string entryPointMangledName; + typedef std::list TGraph; + TGraph callGraph; + + EProfile profile; // source profile + int version; // source version + SpvVersion spvVersion; + TIntermNode* treeRoot; + std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them + TBuiltInResource resources; + int numEntryPoints; + int numErrors; + int numPushConstants; + bool recursive; + bool invertY; + bool useStorageBuffer; + bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN + bool depthReplacing; + int localSize[3]; + bool localSizeNotDefault[3]; + int localSizeSpecId[3]; +#ifndef GLSLANG_WEB +public: + const char* const implicitThisName; + const char* const implicitCounterName; +protected: + EShSource source; // source language, known a bit later + bool useVulkanMemoryModel; + int invocations; + int vertices; + TLayoutGeometry inputPrimitive; + TLayoutGeometry outputPrimitive; + bool pixelCenterInteger; + bool originUpperLeft; + TVertexSpacing vertexSpacing; + TVertexOrder vertexOrder; + TInterlockOrdering interlockOrdering; + bool pointMode; + bool earlyFragmentTests; + bool postDepthCoverage; + TLayoutDepth depthLayout; + bool hlslFunctionality1; + int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift + bool xfbMode; + std::vector xfbBuffers; // all the data we need to track per xfb buffer + bool multiStream; + bool layoutOverrideCoverage; + bool geoPassthroughEXT; + int numShaderRecordBlocks; + ComputeDerivativeMode computeDerivativeMode; + int primitives; + int numTaskNVBlocks; + + // Base shift values + std::array shiftBinding; + + // Per-descriptor-set shift values + std::array, EResCount> shiftBindingForSet; + + std::vector resourceSetBinding; + bool autoMapBindings; + bool autoMapLocations; + bool flattenUniformArrays; + bool useUnknownFormat; + bool hlslOffsets; + bool hlslIoMapping; + bool useVariablePointers; + + std::set semanticNameSet; + + EShTextureSamplerTransformMode textureSamplerTransformMode; + + bool needToLegalize; + bool binaryDoubleOutput; + bool usePhysicalStorageBuffer; + + std::unordered_map uniformLocationOverrides; + int uniformLocationBase; +#endif + + std::unordered_set usedConstantId; // specialization constant ids used + std::vector usedAtomics; // sets of bindings used by atomic counters + std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers + // set of names of statically read/written I/O that might need extra checking + std::set ioAccessed; + // source code of shader, useful as part of debug information + std::string sourceFile; + std::string sourceText; + + // Included text. First string is a name, second is the included text + std::map includeText; + + // for OpModuleProcessed, or equivalent + TProcesses processes; + +private: + void operator=(TIntermediate&); // prevent assignments +}; + +} // end namespace glslang + +#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/parseVersions.h b/ios/include/glslang/MachineIndependent/parseVersions.h new file mode 100644 index 00000000..aa1964fc --- /dev/null +++ b/ios/include/glslang/MachineIndependent/parseVersions.h @@ -0,0 +1,236 @@ +// +// Copyright (C) 2015-2018 Google, Inc. +// Copyright (C) 2017 ARM Limited. +// +// 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. +// + +// This is implemented in Versions.cpp + +#ifndef _PARSE_VERSIONS_INCLUDED_ +#define _PARSE_VERSIONS_INCLUDED_ + +#include "../Public/ShaderLang.h" +#include "../Include/InfoSink.h" +#include "Scan.h" + +#include + +namespace glslang { + +// +// Base class for parse helpers. +// This just has version-related information and checking. +// This class should be sufficient for preprocessing. +// +class TParseVersions { +public: + TParseVersions(TIntermediate& interm, int version, EProfile profile, + const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, + bool forwardCompatible, EShMessages messages) + : +#ifndef GLSLANG_WEB + forwardCompatible(forwardCompatible), + profile(profile), +#endif + infoSink(infoSink), version(version), + language(language), + spvVersion(spvVersion), + intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { } + virtual ~TParseVersions() { } + void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); + void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); +#ifdef GLSLANG_WEB + const EProfile profile = EEsProfile; + bool isEsProfile() const { return true; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) + { + if (! (EEsProfile & profileMask)) + error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc) + { + if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion)) + error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); + } + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc) + { + profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); + } + void initializeExtensionBehavior() { } + void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { } + void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { } + void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc) { } + TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; } + bool extensionTurnedOn(const char* const extension) { return false; } + bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; } + void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { } + void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { } + void checkExtensionStage(const TSourceLoc&, const char* const extension) { } + void fullIntegerCheck(const TSourceLoc&, const char* op) { } + void doubleCheck(const TSourceLoc&, const char* op) { } + bool float16Arithmetic() { return false; } + void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int16Arithmetic() { return false; } + void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + bool int8Arithmetic() { return false; } + void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { } + void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { } + bool relaxedErrors() const { return false; } + bool suppressWarnings() const { return true; } + bool isForwardCompatible() const { return false; } +#else + bool forwardCompatible; // true if errors are to be given for use of deprecated features + EProfile profile; // the declared profile in the shader (core by default) + bool isEsProfile() const { return profile == EEsProfile; } + void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, + const char* const extensions[], const char* featureDesc); + void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, + const char* featureDesc); + virtual void initializeExtensionBehavior(); + virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc); + virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc); + virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual TExtensionBehavior getExtensionBehavior(const char*); + virtual bool extensionTurnedOn(const char* const extension); + virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]); + virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior); + virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); + virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], + const char* featureDesc); + virtual void checkExtensionStage(const TSourceLoc&, const char* const extension); + virtual void fullIntegerCheck(const TSourceLoc&, const char* op); + + virtual void unimplemented(const TSourceLoc&, const char* featureDesc); + virtual void doubleCheck(const TSourceLoc&, const char* op); + virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool float16Arithmetic(); + virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int16Arithmetic(); + virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual bool int8Arithmetic(); + virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); + virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false); + virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false); + bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } + bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } + bool isForwardCompatible() const { return forwardCompatible; } +#endif // GLSLANG_WEB + virtual void spvRemoved(const TSourceLoc&, const char* op); + virtual void vulkanRemoved(const TSourceLoc&, const char* op); + virtual void requireVulkan(const TSourceLoc&, const char* op); + virtual void requireSpv(const TSourceLoc&, const char* op); + + +#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL) + void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } + void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { addError(); } + void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) { } +#else + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...) = 0; +#endif + + void addError() { ++numErrors; } + int getNumErrors() const { return numErrors; } + + void setScanner(TInputScanner* scanner) { currentScanner = scanner; } + TInputScanner* getScanner() const { return currentScanner; } + const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); } + void setCurrentLine(int line) { currentScanner->setLine(line); } + void setCurrentColumn(int col) { currentScanner->setColumn(col); } + void setCurrentSourceName(const char* name) { currentScanner->setFile(name); } + void setCurrentString(int string) { currentScanner->setString(string); } + + void getPreamble(std::string&); +#ifdef ENABLE_HLSL + bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } + bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } + bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; } +#else + bool isReadingHLSL() const { return false; } +#endif + + TInfoSink& infoSink; + + // compilation mode + int version; // version, updated by #version in the shader + EShLanguage language; // really the stage + SpvVersion spvVersion; + TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree + +protected: + TMap extensionBehavior; // for each extension string, what its current behavior is set to + EShMessages messages; // errors/warnings/rule-sets + int numErrors; // number of compile-time errors encountered + TInputScanner* currentScanner; + +private: + explicit TParseVersions(const TParseVersions&); + TParseVersions& operator=(const TParseVersions&); +}; + +} // end namespace glslang + +#endif // _PARSE_VERSIONS_INCLUDED_ diff --git a/ios/include/glslang/MachineIndependent/preprocessor/PpContext.h b/ios/include/glslang/MachineIndependent/preprocessor/PpContext.h new file mode 100644 index 00000000..714b5ead --- /dev/null +++ b/ios/include/glslang/MachineIndependent/preprocessor/PpContext.h @@ -0,0 +1,703 @@ +// +// Copyright (C) 2013 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. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PPCONTEXT_H +#define PPCONTEXT_H + +#include +#include +#include + +#include "../ParseHelper.h" +#include "PpTokens.h" + +/* windows only pragma */ +#ifdef _MSC_VER + #pragma warning(disable : 4127) +#endif + +namespace glslang { + +class TPpToken { +public: + TPpToken() { clear(); } + void clear() + { + space = false; + i64val = 0; + loc.init(); + name[0] = 0; + } + + // Used for comparing macro definitions, so checks what is relevant for that. + bool operator==(const TPpToken& right) const + { + return space == right.space && + ival == right.ival && dval == right.dval && i64val == right.i64val && + strncmp(name, right.name, MaxTokenLength) == 0; + } + bool operator!=(const TPpToken& right) const { return ! operator==(right); } + + TSourceLoc loc; + // True if a space (for white space or a removed comment) should also be + // recognized, in front of the token returned: + bool space; + // Numeric value of the token: + union { + int ival; + double dval; + long long i64val; + }; + // Text string of the token: + char name[MaxTokenLength + 1]; +}; + +class TStringAtomMap { +// +// Implementation is in PpAtom.cpp +// +// Maintain a bi-directional mapping between relevant preprocessor strings and +// "atoms" which a unique integers (small, contiguous, not hash-like) per string. +// +public: + TStringAtomMap(); + + // Map string -> atom. + // Return 0 if no existing string. + int getAtom(const char* s) const + { + auto it = atomMap.find(s); + return it == atomMap.end() ? 0 : it->second; + } + + // Map a new or existing string -> atom, inventing a new atom if necessary. + int getAddAtom(const char* s) + { + int atom = getAtom(s); + if (atom == 0) { + atom = nextAtom++; + addAtomFixed(s, atom); + } + return atom; + } + + // Map atom -> string. + const char* getString(int atom) const { return stringMap[atom]->c_str(); } + +protected: + TStringAtomMap(TStringAtomMap&); + TStringAtomMap& operator=(TStringAtomMap&); + + TUnorderedMap atomMap; + TVector stringMap; // these point into the TString in atomMap + int nextAtom; + + // Bad source characters can lead to bad atoms, so gracefully handle those by + // pre-filling the table with them (to avoid if tests later). + TString badToken; + + // Add bi-directional mappings: + // - string -> atom + // - atom -> string + void addAtomFixed(const char* s, int atom) + { + auto it = atomMap.insert(std::pair(s, atom)).first; + if (stringMap.size() < (size_t)atom + 1) + stringMap.resize(atom + 100, &badToken); + stringMap[atom] = &it->first; + } +}; + +class TInputScanner; + +enum MacroExpandResult { + MacroExpandNotStarted, // macro not expanded, which might not be an error + MacroExpandError, // a clear error occurred while expanding, no expansion + MacroExpandStarted, // macro expansion process has started + MacroExpandUndef // macro is undefined and will be expanded +}; + +// This class is the result of turning a huge pile of C code communicating through globals +// into a class. This was done to allowing instancing to attain thread safety. +// Don't expect too much in terms of OO design. +class TPpContext { +public: + TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); + virtual ~TPpContext(); + + void setPreamble(const char* preamble, size_t length); + + int tokenize(TPpToken& ppToken); + int tokenPaste(int token, TPpToken&); + + class tInput { + public: + tInput(TPpContext* p) : done(false), pp(p) { } + virtual ~tInput() { } + + virtual int scan(TPpToken*) = 0; + virtual int getch() = 0; + virtual void ungetch() = 0; + virtual bool peekPasting() { return false; } // true when about to see ## + virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste + virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define) + virtual bool isMacroInput() { return false; } + + // Will be called when we start reading tokens from this instance + virtual void notifyActivated() {} + // Will be called when we do not read tokens from this instance anymore + virtual void notifyDeleted() {} + protected: + bool done; + TPpContext* pp; + }; + + void setInput(TInputScanner& input, bool versionWillBeError); + + void pushInput(tInput* in) + { + inputStack.push_back(in); + in->notifyActivated(); + } + void popInput() + { + inputStack.back()->notifyDeleted(); + delete inputStack.back(); + inputStack.pop_back(); + } + + // + // From PpTokens.cpp + // + + // Capture the needed parts of a token stream for macro recording/playback. + class TokenStream { + public: + // Manage a stream of these 'Token', which capture the relevant parts + // of a TPpToken, plus its atom. + class Token { + public: + Token(int atom, const TPpToken& ppToken) : + atom(atom), + space(ppToken.space), + i64val(ppToken.i64val), + name(ppToken.name) { } + int get(TPpToken& ppToken) + { + ppToken.clear(); + ppToken.space = space; + ppToken.i64val = i64val; + snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str()); + return atom; + } + bool isAtom(int a) const { return atom == a; } + int getAtom() const { return atom; } + bool nonSpaced() const { return !space; } + protected: + Token() {} + int atom; + bool space; // did a space precede the token? + long long i64val; + TString name; + }; + + TokenStream() : currentPos(0) { } + + void putToken(int token, TPpToken* ppToken); + bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); } + bool peekContinuedPasting(int atom) + { + // This is basically necessary because, for example, the PP + // tokenizer only accepts valid numeric-literals plus suffixes, so + // separates numeric-literals plus bad suffix into two tokens, which + // should get both pasted together as one token when token pasting. + // + // The following code is a bit more generalized than the above example. + if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) { + switch(stream[currentPos].getAtom()) { + case PpAtomConstInt: + case PpAtomConstUint: + case PpAtomConstInt64: + case PpAtomConstUint64: + case PpAtomConstInt16: + case PpAtomConstUint16: + case PpAtomConstFloat: + case PpAtomConstDouble: + case PpAtomConstFloat16: + case PpAtomConstString: + case PpAtomIdentifier: + return true; + default: + break; + } + } + + return false; + } + int getToken(TParseContextBase&, TPpToken*); + bool atEnd() { return currentPos >= stream.size(); } + bool peekTokenizedPasting(bool lastTokenPastes); + bool peekUntokenizedPasting(); + void reset() { currentPos = 0; } + + protected: + TVector stream; + size_t currentPos; + }; + + // + // From Pp.cpp + // + + struct MacroSymbol { + MacroSymbol() : functionLike(0), busy(0), undef(0) { } + TVector args; + TokenStream body; + unsigned functionLike : 1; // 0 means object-like, 1 means function-like + unsigned busy : 1; + unsigned undef : 1; + }; + + typedef TMap TSymbolMap; + TSymbolMap macroDefs; // map atoms to macro definitions + MacroSymbol* lookupMacroDef(int atom) + { + auto existingMacroIt = macroDefs.find(atom); + return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second); + } + void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; } + +protected: + TPpContext(TPpContext&); + TPpContext& operator=(TPpContext&); + + TStringAtomMap atomStrings; + char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble + int preambleLength; + char** strings; // official strings of shader, starting a string 0 line 1 + size_t* lengths; + int numStrings; // how many official strings there are + int currentString; // which string we're currently parsing (-1 for preamble) + + // Scanner data: + int previous_token; + TParseContextBase& parseContext; + + // Get the next token from *stack* of input sources, popping input sources + // that are out of tokens, down until an input source is found that has a token. + // Return EndOfInput when there are no more tokens to be found by doing this. + int scanToken(TPpToken* ppToken) + { + int token = EndOfInput; + + while (! inputStack.empty()) { + token = inputStack.back()->scan(ppToken); + if (token != EndOfInput || inputStack.empty()) + break; + popInput(); + } + + return token; + } + int getChar() { return inputStack.back()->getch(); } + void ungetChar() { inputStack.back()->ungetch(); } + bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); } + bool peekContinuedPasting(int a) + { + return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a); + } + bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); } + bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); } + + static const int maxIfNesting = 65; + + int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor) + bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth + int elsetracker; // #if-#else and #endif constructs...Counter. + + class tMacroInput : public tInput { + public: + tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { } + virtual ~tMacroInput() + { + for (size_t i = 0; i < args.size(); ++i) + delete args[i]; + for (size_t i = 0; i < expandedArgs.size(); ++i) + delete expandedArgs[i]; + } + + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + bool peekPasting() override { return prepaste; } + bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); } + bool endOfReplacementList() override { return mac->body.atEnd(); } + bool isMacroInput() override { return true; } + + MacroSymbol *mac; + TVector args; + TVector expandedArgs; + + protected: + bool prepaste; // true if we are just before ## + bool postpaste; // true if we are right after ## + }; + + class tMarkerInput : public tInput { + public: + tMarkerInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override + { + if (done) + return EndOfInput; + done = true; + + return marker; + } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + static const int marker = -3; + }; + + class tZeroInput : public tInput { + public: + tZeroInput(TPpContext* pp) : tInput(pp) { } + virtual int scan(TPpToken*) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + }; + + std::vector inputStack; + bool errorOnVersion; + bool versionSeen; + + // + // from Pp.cpp + // + + // Used to obtain #include content. + TShader::Includer& includer; + + int CPPdefine(TPpToken * ppToken); + int CPPundef(TPpToken * ppToken); + int CPPelse(int matchelse, TPpToken * ppToken); + int extraTokenCheck(int atom, TPpToken* ppToken, int token); + int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); + int CPPif (TPpToken * ppToken); + int CPPifdef(int defined, TPpToken * ppToken); + int CPPinclude(TPpToken * ppToken); + int CPPline(TPpToken * ppToken); + int CPPerror(TPpToken * ppToken); + int CPPpragma(TPpToken * ppToken); + int CPPversion(TPpToken * ppToken); + int CPPextension(TPpToken * ppToken); + int readCPPline(TPpToken * ppToken); + int scanHeaderName(TPpToken* ppToken, char delimit); + TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay); + MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay); + + // + // From PpTokens.cpp + // + void pushTokenStreamInput(TokenStream&, bool pasting = false); + void UngetToken(int token, TPpToken*); + + class tTokenInput : public tInput { + public: + tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : + tInput(pp), + tokens(t), + lastTokenPastes(prepasting) { } + virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); } + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); } + bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); } + protected: + TokenStream* tokens; + bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token + }; + + class tUngotTokenInput : public tInput { + public: + tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } + virtual int scan(TPpToken *) override; + virtual int getch() override { assert(0); return EndOfInput; } + virtual void ungetch() override { assert(0); } + protected: + int token; + TPpToken lval; + }; + + // + // From PpScanner.cpp + // + class tStringInput : public tInput { + public: + tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { } + virtual int scan(TPpToken*) override; + + // Scanner used to get source stream characters. + // - Escaped newlines are handled here, invisibly to the caller. + // - All forms of newline are handled, and turned into just a '\n'. + int getch() override + { + int ch = input->get(); + + if (ch == '\\') { + // Move past escaped newlines, as many as sequentially exist + do { + if (input->peek() == '\r' || input->peek() == '\n') { + bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment); + if (! allowed && pp->inComment) + return '\\'; + + // escape one newline now + ch = input->get(); + int nextch = input->get(); + if (ch == '\r' && nextch == '\n') + ch = input->get(); + else + ch = nextch; + } else + return '\\'; + } while (ch == '\\'); + } + + // handle any non-escaped newline + if (ch == '\r' || ch == '\n') { + if (ch == '\r' && input->peek() == '\n') + input->get(); + return '\n'; + } + + return ch; + } + + // Scanner used to backup the source stream characters. Newlines are + // handled here, invisibly to the caller, meaning have to undo exactly + // what getch() above does (e.g., don't leave things in the middle of a + // sequence of escaped newlines). + void ungetch() override + { + input->unget(); + + do { + int ch = input->peek(); + if (ch == '\r' || ch == '\n') { + if (ch == '\n') { + // correct for two-character newline + input->unget(); + if (input->peek() != '\r') + input->get(); + } + // now in front of a complete newline, move past an escape character + input->unget(); + if (input->peek() == '\\') + input->unget(); + else { + input->get(); + break; + } + } else + break; + } while (true); + } + + protected: + TInputScanner* input; + }; + + // Holds a reference to included file data, as well as a + // prologue and an epilogue string. This can be scanned using the tInput + // interface and acts as a single source string. + class TokenizableIncludeFile : public tInput { + public: + // Copies prologue and epilogue. The includedFile must remain valid + // until this TokenizableIncludeFile is no longer used. + TokenizableIncludeFile(const TSourceLoc& startLoc, + const std::string& prologue, + TShader::Includer::IncludeResult* includedFile, + const std::string& epilogue, + TPpContext* pp) + : tInput(pp), + prologue_(prologue), + epilogue_(epilogue), + includedFile_(includedFile), + scanner(3, strings, lengths, nullptr, 0, 0, true), + prevScanner(nullptr), + stringInput(pp, scanner) + { + strings[0] = prologue_.data(); + strings[1] = includedFile_->headerData; + strings[2] = epilogue_.data(); + + lengths[0] = prologue_.size(); + lengths[1] = includedFile_->headerLength; + lengths[2] = epilogue_.size(); + + scanner.setLine(startLoc.line); + scanner.setString(startLoc.string); + + scanner.setFile(startLoc.getFilenameStr(), 0); + scanner.setFile(startLoc.getFilenameStr(), 1); + scanner.setFile(startLoc.getFilenameStr(), 2); + } + + // tInput methods: + int scan(TPpToken* t) override { return stringInput.scan(t); } + int getch() override { return stringInput.getch(); } + void ungetch() override { stringInput.ungetch(); } + + void notifyActivated() override + { + prevScanner = pp->parseContext.getScanner(); + pp->parseContext.setScanner(&scanner); + pp->push_include(includedFile_); + } + + void notifyDeleted() override + { + pp->parseContext.setScanner(prevScanner); + pp->pop_include(); + } + + private: + TokenizableIncludeFile& operator=(const TokenizableIncludeFile&); + + // Stores the prologue for this string. + const std::string prologue_; + + // Stores the epilogue for this string. + const std::string epilogue_; + + // Points to the IncludeResult that this TokenizableIncludeFile represents. + TShader::Includer::IncludeResult* includedFile_; + + // Will point to prologue_, includedFile_->headerData and epilogue_ + // This is passed to scanner constructor. + // These do not own the storage and it must remain valid until this + // object has been destroyed. + const char* strings[3]; + // Length of str_, passed to scanner constructor. + size_t lengths[3]; + // Scans over str_. + TInputScanner scanner; + // The previous effective scanner before the scanner in this instance + // has been activated. + TInputScanner* prevScanner; + // Delegate object implementing the tInput interface. + tStringInput stringInput; + }; + + int ScanFromString(char* s); + void missingEndifCheck(); + int lFloatConst(int len, int ch, TPpToken* ppToken); + int characterLiteral(TPpToken* ppToken); + + void push_include(TShader::Includer::IncludeResult* result) + { + currentSourceFile = result->headerName; + includeStack.push(result); + } + + void pop_include() + { + TShader::Includer::IncludeResult* include = includeStack.top(); + includeStack.pop(); + includer.releaseInclude(include); + if (includeStack.empty()) { + currentSourceFile = rootFileName; + } else { + currentSourceFile = includeStack.top()->headerName; + } + } + + bool inComment; + std::string rootFileName; + std::stack includeStack; + std::string currentSourceFile; + + std::istringstream strtodStream; + bool disableEscapeSequences; +}; + +} // end namespace glslang + +#endif // PPCONTEXT_H diff --git a/ios/include/glslang/MachineIndependent/preprocessor/PpTokens.h b/ios/include/glslang/MachineIndependent/preprocessor/PpTokens.h new file mode 100644 index 00000000..7b0f8155 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/preprocessor/PpTokens.h @@ -0,0 +1,179 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// 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. +// +/****************************************************************************\ +Copyright (c) 2002, NVIDIA Corporation. + +NVIDIA Corporation("NVIDIA") supplies this software to you in +consideration of your agreement to the following terms, and your use, +installation, modification or redistribution of this NVIDIA software +constitutes acceptance of these terms. If you do not agree with these +terms, please do not use, install, modify or redistribute this NVIDIA +software. + +In consideration of your agreement to abide by the following terms, and +subject to these terms, NVIDIA grants you a personal, non-exclusive +license, under NVIDIA's copyrights in this original NVIDIA software (the +"NVIDIA Software"), to use, reproduce, modify and redistribute the +NVIDIA Software, with or without modifications, in source and/or binary +forms; provided that if you redistribute the NVIDIA Software, you must +retain the copyright notice of NVIDIA, this notice and the following +text and disclaimers in all such redistributions of the NVIDIA Software. +Neither the name, trademarks, service marks nor logos of NVIDIA +Corporation may be used to endorse or promote products derived from the +NVIDIA Software without specific prior written permission from NVIDIA. +Except as expressly stated in this notice, no other rights or licenses +express or implied, are granted by NVIDIA herein, including but not +limited to any patent rights that may be infringed by your derivative +works or by other works in which the NVIDIA Software may be +incorporated. No hardware is licensed hereunder. + +THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, +INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR +ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER +PRODUCTS. + +IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, +INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY +OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE +NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, +TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\****************************************************************************/ + +#ifndef PARSER_H +#define PARSER_H + +namespace glslang { + +// Multi-character tokens +enum EFixedAtoms { + // single character tokens get their own char value as their token; start here for multi-character tokens + PpAtomMaxSingle = 127, + + // replace bad character tokens with this, to avoid accidental aliasing with the below + PpAtomBadToken, + + // Operators + + PPAtomAddAssign, + PPAtomSubAssign, + PPAtomMulAssign, + PPAtomDivAssign, + PPAtomModAssign, + + PpAtomRight, + PpAtomLeft, + + PpAtomRightAssign, + PpAtomLeftAssign, + PpAtomAndAssign, + PpAtomOrAssign, + PpAtomXorAssign, + + PpAtomAnd, + PpAtomOr, + PpAtomXor, + + PpAtomEQ, + PpAtomNE, + PpAtomGE, + PpAtomLE, + + PpAtomDecrement, + PpAtomIncrement, + + PpAtomColonColon, + + PpAtomPaste, + + // Constants + + PpAtomConstInt, + PpAtomConstUint, + PpAtomConstInt64, + PpAtomConstUint64, + PpAtomConstInt16, + PpAtomConstUint16, + PpAtomConstFloat, + PpAtomConstDouble, + PpAtomConstFloat16, + PpAtomConstString, + + // Identifiers + PpAtomIdentifier, + + // preprocessor "keywords" + + PpAtomDefine, + PpAtomUndef, + + PpAtomIf, + PpAtomIfdef, + PpAtomIfndef, + PpAtomElse, + PpAtomElif, + PpAtomEndif, + + PpAtomLine, + PpAtomPragma, + PpAtomError, + + // #version ... + PpAtomVersion, + PpAtomCore, + PpAtomCompatibility, + PpAtomEs, + + // #extension + PpAtomExtension, + + // __LINE__, __FILE__, __VERSION__ + + PpAtomLineMacro, + PpAtomFileMacro, + PpAtomVersionMacro, + + // #include + PpAtomInclude, + + PpAtomLast, +}; + +} // end namespace glslang + +#endif /* not PARSER_H */ diff --git a/ios/include/glslang/MachineIndependent/propagateNoContraction.h b/ios/include/glslang/MachineIndependent/propagateNoContraction.h new file mode 100644 index 00000000..8521ad7d --- /dev/null +++ b/ios/include/glslang/MachineIndependent/propagateNoContraction.h @@ -0,0 +1,55 @@ +// +// Copyright (C) 2015-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. + +// +// Visit the nodes in the glslang intermediate tree representation to +// propagate 'noContraction' qualifier. +// + +#pragma once + +#include "../Include/intermediate.h" + +namespace glslang { + +// Propagates the 'precise' qualifier for objects (objects marked with +// 'noContraction' qualifier) from the shader source specified 'precise' +// variables to all the involved objects, and add 'noContraction' qualifier for +// the involved arithmetic operations. +// Note that the same qualifier: 'noContraction' is used in both object nodes +// and arithmetic operation nodes, but has different meaning. For object nodes, +// 'noContraction' means the object is 'precise'; and for arithmetic operation +// nodes, it means the operation should not be contracted. +void PropagateNoContraction(const glslang::TIntermediate& intermediate); +}; diff --git a/ios/include/glslang/MachineIndependent/reflection.h b/ios/include/glslang/MachineIndependent/reflection.h new file mode 100644 index 00000000..0c33de45 --- /dev/null +++ b/ios/include/glslang/MachineIndependent/reflection.h @@ -0,0 +1,223 @@ +// +// Copyright (C) 2013-2016 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 GLSLANG_WEB + +#ifndef _REFLECTION_INCLUDED +#define _REFLECTION_INCLUDED + +#include "../Public/ShaderLang.h" +#include "../Include/Types.h" + +#include +#include + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +namespace glslang { + +class TIntermediate; +class TIntermAggregate; +class TReflectionTraverser; + +// The full reflection database +class TReflection { +public: + TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) + : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) + { + for (int dim=0; dim<3; ++dim) + localSize[dim] = 0; + } + + virtual ~TReflection() {} + + // grow the reflection stage by stage + bool addStage(EShLanguage, const TIntermediate&); + + // for mapping a uniform index to a uniform object's description + int getNumUniforms() { return (int)indexToUniform.size(); } + const TObjectReflection& getUniform(int i) const + { + if (i >= 0 && i < (int)indexToUniform.size()) + return indexToUniform[i]; + else + return badReflection; + } + + // for mapping a block index to the block's description + int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } + const TObjectReflection& getUniformBlock(int i) const + { + if (i >= 0 && i < (int)indexToUniformBlock.size()) + return indexToUniformBlock[i]; + else + return badReflection; + } + + // for mapping an pipeline input index to the input's description + int getNumPipeInputs() { return (int)indexToPipeInput.size(); } + const TObjectReflection& getPipeInput(int i) const + { + if (i >= 0 && i < (int)indexToPipeInput.size()) + return indexToPipeInput[i]; + else + return badReflection; + } + + // for mapping an pipeline output index to the output's description + int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } + const TObjectReflection& getPipeOutput(int i) const + { + if (i >= 0 && i < (int)indexToPipeOutput.size()) + return indexToPipeOutput[i]; + else + return badReflection; + } + + // for mapping from an atomic counter to the uniform index + int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } + const TObjectReflection& getAtomicCounter(int i) const + { + if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) + return getUniform(atomicCounterUniformIndices[i]); + else + return badReflection; + } + + // for mapping a buffer variable index to a buffer variable object's description + int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } + const TObjectReflection& getBufferVariable(int i) const + { + if (i >= 0 && i < (int)indexToBufferVariable.size()) + return indexToBufferVariable[i]; + else + return badReflection; + } + + // for mapping a storage block index to the storage block's description + int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } + const TObjectReflection& getStorageBufferBlock(int i) const + { + if (i >= 0 && i < (int)indexToBufferBlock.size()) + return indexToBufferBlock[i]; + else + return badReflection; + } + + // for mapping any name to its index (block names, uniform names and input/output names) + int getIndex(const char* name) const + { + TNameToIndex::const_iterator it = nameToIndex.find(name); + if (it == nameToIndex.end()) + return -1; + else + return it->second; + } + + // see getIndex(const char*) + int getIndex(const TString& name) const { return getIndex(name.c_str()); } + + + // for mapping any name to its index (only pipe input/output names) + int getPipeIOIndex(const char* name, const bool inOrOut) const + { + TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); + if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) + return -1; + else + return it->second; + } + + // see gePipeIOIndex(const char*, const bool) + int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } + + // Thread local size + unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } + + void dump(); + +protected: + friend class glslang::TReflectionTraverser; + + void buildCounterIndices(const TIntermediate&); + void buildUniformStageMask(const TIntermediate& intermediate); + void buildAttributeReflection(EShLanguage, const TIntermediate&); + + // Need a TString hash: typedef std::unordered_map TNameToIndex; + typedef std::map TNameToIndex; + typedef std::vector TMapIndexToReflection; + typedef std::vector TIndices; + + TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferBlock; + return indexToUniformBlock; + } + TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) + { + if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) + return indexToBufferVariable; + return indexToUniform; + } + + EShReflectionOptions options; + + EShLanguage firstStage; + EShLanguage lastStage; + + TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this + TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed + TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. + TMapIndexToReflection indexToUniform; + TMapIndexToReflection indexToUniformBlock; + TMapIndexToReflection indexToBufferVariable; + TMapIndexToReflection indexToBufferBlock; + TMapIndexToReflection indexToPipeInput; + TMapIndexToReflection indexToPipeOutput; + TIndices atomicCounterUniformIndices; + + unsigned int localSize[3]; +}; + +} // end namespace glslang + +#endif // _REFLECTION_INCLUDED + +#endif // GLSLANG_WEB diff --git a/ios/include/glslang/Public/ShaderLang.h b/ios/include/glslang/Public/ShaderLang.h new file mode 100644 index 00000000..acb2a078 --- /dev/null +++ b/ios/include/glslang/Public/ShaderLang.h @@ -0,0 +1,927 @@ +// +// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. +// Copyright (C) 2013-2016 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. +// +#ifndef _COMPILER_INTERFACE_INCLUDED_ +#define _COMPILER_INTERFACE_INCLUDED_ + +#include "../Include/ResourceLimits.h" +#include "../MachineIndependent/Versions.h" + +#include +#include + +#ifdef _WIN32 +#define C_DECL __cdecl +//#ifdef SH_EXPORTING +// #define SH_IMPORT_EXPORT __declspec(dllexport) +//#else +// #define SH_IMPORT_EXPORT __declspec(dllimport) +//#endif +#define SH_IMPORT_EXPORT +#else +#define SH_IMPORT_EXPORT +#define C_DECL +#endif + +// +// This is the platform independent interface between an OGL driver +// and the shading language compiler/linker. +// + +#ifdef __cplusplus + extern "C" { +#endif + +// This should always increase, as some paths to do not consume +// a more major number. +// It should increment by one when new functionality is added. +#define GLSLANG_MINOR_VERSION 13 + +// +// Call before doing any other compiler/linker operations. +// +// (Call once per process, not once per thread.) +// +SH_IMPORT_EXPORT int ShInitialize(); + +// +// Call this at process shutdown to clean up memory. +// +SH_IMPORT_EXPORT int ShFinalize(); + +// +// Types of languages the compiler can consume. +// +typedef enum { + EShLangVertex, + EShLangTessControl, + EShLangTessEvaluation, + EShLangGeometry, + EShLangFragment, + EShLangCompute, + EShLangRayGen, + EShLangRayGenNV = EShLangRayGen, + EShLangIntersect, + EShLangIntersectNV = EShLangIntersect, + EShLangAnyHit, + EShLangAnyHitNV = EShLangAnyHit, + EShLangClosestHit, + EShLangClosestHitNV = EShLangClosestHit, + EShLangMiss, + EShLangMissNV = EShLangMiss, + EShLangCallable, + EShLangCallableNV = EShLangCallable, + EShLangTaskNV, + EShLangMeshNV, + LAST_ELEMENT_MARKER(EShLangCount), +} EShLanguage; // would be better as stage, but this is ancient now + +typedef enum { + EShLangVertexMask = (1 << EShLangVertex), + EShLangTessControlMask = (1 << EShLangTessControl), + EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), + EShLangGeometryMask = (1 << EShLangGeometry), + EShLangFragmentMask = (1 << EShLangFragment), + EShLangComputeMask = (1 << EShLangCompute), + EShLangRayGenMask = (1 << EShLangRayGen), + EShLangRayGenNVMask = EShLangRayGenMask, + EShLangIntersectMask = (1 << EShLangIntersect), + EShLangIntersectNVMask = EShLangIntersectMask, + EShLangAnyHitMask = (1 << EShLangAnyHit), + EShLangAnyHitNVMask = EShLangAnyHitMask, + EShLangClosestHitMask = (1 << EShLangClosestHit), + EShLangClosestHitNVMask = EShLangClosestHitMask, + EShLangMissMask = (1 << EShLangMiss), + EShLangMissNVMask = EShLangMissMask, + EShLangCallableMask = (1 << EShLangCallable), + EShLangCallableNVMask = EShLangCallableMask, + EShLangTaskNVMask = (1 << EShLangTaskNV), + EShLangMeshNVMask = (1 << EShLangMeshNV), + LAST_ELEMENT_MARKER(EShLanguageMaskCount), +} EShLanguageMask; + +namespace glslang { + +class TType; + +typedef enum { + EShSourceNone, + EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) + EShSourceHlsl, // HLSL + LAST_ELEMENT_MARKER(EShSourceCount), +} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead + +typedef enum { + EShClientNone, // use when there is no client, e.g. for validation + EShClientVulkan, + EShClientOpenGL, + LAST_ELEMENT_MARKER(EShClientCount), +} EShClient; + +typedef enum { + EShTargetNone, + EShTargetSpv, // SPIR-V (preferred spelling) + EshTargetSpv = EShTargetSpv, // legacy spelling + LAST_ELEMENT_MARKER(EShTargetCount), +} EShTargetLanguage; + +typedef enum { + EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 + EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 + EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 + EShTargetOpenGL_450 = 450, // OpenGL + LAST_ELEMENT_MARKER(EShTargetClientVersionCount), +} EShTargetClientVersion; + +typedef EShTargetClientVersion EshTargetClientVersion; + +typedef enum { + EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0 + EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1 + EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2 + EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 + EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 + EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 + LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount), +} EShTargetLanguageVersion; + +struct TInputLanguage { + EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone + EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone + EShClient dialect; + int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) +}; + +struct TClient { + EShClient client; + EShTargetClientVersion version; // version of client itself (not the client's input dialect) +}; + +struct TTarget { + EShTargetLanguage language; + EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header + bool hlslFunctionality1; // can target hlsl_functionality1 extension(s) +}; + +// All source/client/target versions and settings. +// Can override previous methods of setting, when items are set here. +// Expected to grow, as more are added, rather than growing parameter lists. +struct TEnvironment { + TInputLanguage input; // definition of the input language + TClient client; // what client is the overall compilation being done for? + TTarget target; // what to generate +}; + +const char* StageName(EShLanguage); + +} // end namespace glslang + +// +// Types of output the linker will create. +// +typedef enum { + EShExVertexFragment, + EShExFragment +} EShExecutable; + +// +// Optimization level for the compiler. +// +typedef enum { + EShOptNoGeneration, + EShOptNone, + EShOptSimple, // Optimizations that can be done quickly + EShOptFull, // Optimizations that will take more time + LAST_ELEMENT_MARKER(EshOptLevelCount), +} EShOptimizationLevel; + +// +// Texture and Sampler transformation mode. +// +typedef enum { + EShTexSampTransKeep, // keep textures and samplers as is (default) + EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers + LAST_ELEMENT_MARKER(EShTexSampTransCount), +} EShTextureSamplerTransformMode; + +// +// Message choices for what errors and warnings are given. +// +enum EShMessages { + EShMsgDefault = 0, // default is to give all required errors and extra warnings + EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input + EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification + EShMsgAST = (1 << 2), // print the AST intermediate representation + EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation + EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V + EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor + EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics + EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit + EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions + EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules + EShMsgDebugInfo = (1 << 10), // save debug information + EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL + EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages + EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers) + EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table + LAST_ELEMENT_MARKER(EShMsgCount), +}; + +// +// Options for building reflection +// +typedef enum { + EShReflectionDefault = 0, // default is original behaviour before options were added + EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes + EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection + EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader + EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately + EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive + EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks + LAST_ELEMENT_MARKER(EShReflectionCount), +} EShReflectionOptions; + +// +// Build a table for bindings. This can be used for locating +// attributes, uniforms, globals, etc., as needed. +// +typedef struct { + const char* name; + int binding; +} ShBinding; + +typedef struct { + int numBindings; + ShBinding* bindings; // array of bindings +} ShBindingTable; + +// +// ShHandle held by but opaque to the driver. It is allocated, +// managed, and de-allocated by the compiler/linker. It's contents +// are defined by and used by the compiler and linker. For example, +// symbol table information and object code passed from the compiler +// to the linker can be stored where ShHandle points. +// +// If handle creation fails, 0 will be returned. +// +typedef void* ShHandle; + +// +// Driver calls these to create and destroy compiler/linker +// objects. +// +SH_IMPORT_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int debugOptions); // one per shader +SH_IMPORT_EXPORT ShHandle ShConstructLinker(const EShExecutable, int debugOptions); // one per shader pair +SH_IMPORT_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) +SH_IMPORT_EXPORT void ShDestruct(ShHandle); + +// +// The return value of ShCompile is boolean, non-zero indicating +// success. +// +// The info-log should be written by ShCompile into +// ShHandle, so it can answer future queries. +// +SH_IMPORT_EXPORT int ShCompile( + const ShHandle, + const char* const shaderStrings[], + const int numStrings, + const int* lengths, + const EShOptimizationLevel, + const TBuiltInResource *resources, + int debugOptions, + int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader + bool forwardCompatible = false, // give errors for use of deprecated features + EShMessages messages = EShMsgDefault // warnings and errors + ); + +SH_IMPORT_EXPORT int ShLinkExt( + const ShHandle, // linker object + const ShHandle h[], // compiler objects to link together + const int numHandles); + +// +// ShSetEncrpytionMethod is a place-holder for specifying +// how source code is encrypted. +// +SH_IMPORT_EXPORT void ShSetEncryptionMethod(ShHandle); + +// +// All the following return 0 if the information is not +// available in the object passed down, or the object is bad. +// +SH_IMPORT_EXPORT const char* ShGetInfoLog(const ShHandle); +SH_IMPORT_EXPORT const void* ShGetExecutable(const ShHandle); +SH_IMPORT_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing +SH_IMPORT_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings +// +// Tell the linker to never assign a vertex attribute to this list of physical attributes +// +SH_IMPORT_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); + +// +// Returns the location ID of the named uniform. +// Returns -1 if error. +// +SH_IMPORT_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); + +#ifdef __cplusplus + } // end extern "C" +#endif + +//////////////////////////////////////////////////////////////////////////////////////////// +// +// Deferred-Lowering C++ Interface +// ----------------------------------- +// +// Below is a new alternate C++ interface, which deprecates the above +// opaque handle-based interface. +// +// The below is further designed to handle multiple compilation units per stage, where +// the intermediate results, including the parse tree, are preserved until link time, +// rather than the above interface which is designed to have each compilation unit +// lowered at compile time. In the above model, linking occurs on the lowered results, +// whereas in this model intra-stage linking can occur at the parse tree +// (treeRoot in TIntermediate) level, and then a full stage can be lowered. +// + +#include +#include +#include + +class TCompiler; +class TInfoSink; + +namespace glslang { + +const char* GetEsslVersionString(); +const char* GetGlslVersionString(); +int GetKhronosToolId(); + +class TIntermediate; +class TProgram; +class TPoolAllocator; + +// Call this exactly once per process before using anything else +bool InitializeProcess(); + +// Call once per process to tear down everything +void FinalizeProcess(); + +// Resource type for IO resolver +enum TResourceType { + EResSampler, + EResTexture, + EResImage, + EResUbo, + EResSsbo, + EResUav, + EResCount +}; + +// Make one TShader per shader that you will link into a program. Then +// - provide the shader through setStrings() or setStringsWithLengths() +// - optionally call setEnv*(), see below for more detail +// - optionally use setPreamble() to set a special shader string that will be +// processed before all others but won't affect the validity of #version +// - optionally call addProcesses() for each setting/transform, +// see comment for class TProcesses +// - call parse(): source language and target environment must be selected +// either by correct setting of EShMessages sent to parse(), or by +// explicitly calling setEnv*() +// - query the info logs +// +// N.B.: Does not yet support having the same TShader instance being linked into +// multiple programs. +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TShader { +public: + explicit TShader(EShLanguage); + virtual ~TShader(); + void setStrings(const char* const* s, int n); + void setStringsWithLengths(const char* const* s, const int* l, int n); + void setStringsWithLengthsAndNames( + const char* const* s, const int* l, const char* const* names, int n); + void setPreamble(const char* s) { preamble = s; } + void setEntryPoint(const char* entryPoint); + void setSourceEntryPoint(const char* sourceEntryPointName); + void addProcesses(const std::vector&); + + // IO resolver binding data: see comments in ShaderLang.cpp + void setShiftBinding(TResourceType res, unsigned int base); + void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding + void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding + void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); + void setResourceSetBinding(const std::vector& base); + void setAutoMapBindings(bool map); + void setAutoMapLocations(bool map); + void addUniformLocationOverride(const char* name, int loc); + void setUniformLocationBase(int base); + void setInvertY(bool invert); +#ifdef ENABLE_HLSL + void setHlslIoMapping(bool hlslIoMap); + void setFlattenUniformArrays(bool flatten); +#endif + void setNoStorageFormat(bool useUnknownFormat); + void setNanMinMaxClamp(bool nanMinMaxClamp); + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); + + // For setting up the environment (cleared to nothingness in the constructor). + // These must be called so that parsing is done for the right source language and + // target environment, either indirectly through TranslateEnvironment() based on + // EShMessages et. al., or directly by the user. + // + // setEnvInput: The input source language and stage. If generating code for a + // specific client, the input client semantics to use and the + // version of the that client's input semantics to use, otherwise + // use EShClientNone and version of 0, e.g. for validation mode. + // Note 'version' does not describe the target environment, + // just the version of the source dialect to compile under. + // + // See the definitions of TEnvironment, EShSource, EShLanguage, + // and EShClient for choices and more detail. + // + // setEnvClient: The client that will be hosting the execution, and it's version. + // Note 'version' is not the version of the languages involved, but + // the version of the client environment. + // Use EShClientNone and version of 0 if there is no client, e.g. + // for validation mode. + // + // See EShTargetClientVersion for choices. + // + // setEnvTarget: The language to translate to when generating code, and that + // language's version. + // Use EShTargetNone and version of 0 if there is no client, e.g. + // for validation mode. + // + void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version) + { + environment.input.languageFamily = lang; + environment.input.stage = envStage; + environment.input.dialect = client; + environment.input.dialectVersion = version; + } + void setEnvClient(EShClient client, EShTargetClientVersion version) + { + environment.client.client = client; + environment.client.version = version; + } + void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version) + { + environment.target.language = lang; + environment.target.version = version; + } + + void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; } + +#ifdef ENABLE_HLSL + void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } + bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } +#else + bool getEnvTargetHlslFunctionality1() const { return false; } +#endif + + // Interface to #include handlers. + // + // To support #include, a client of Glslang does the following: + // 1. Call setStringsWithNames to set the source strings and associated + // names. For example, the names could be the names of the files + // containing the shader sources. + // 2. Call parse with an Includer. + // + // When the Glslang parser encounters an #include directive, it calls + // the Includer's include method with the requested include name + // together with the current string name. The returned IncludeResult + // contains the fully resolved name of the included source, together + // with the source text that should replace the #include directive + // in the source stream. After parsing that source, Glslang will + // release the IncludeResult object. + class Includer { + public: + // An IncludeResult contains the resolved name and content of a source + // inclusion. + struct IncludeResult { + IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : + headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } + // For a successful inclusion, the fully resolved name of the requested + // include. For example, in a file system-based includer, full resolution + // should convert a relative path name into an absolute path name. + // For a failed inclusion, this is an empty string. + const std::string headerName; + // The content and byte length of the requested inclusion. The + // Includer producing this IncludeResult retains ownership of the + // storage. + // For a failed inclusion, the header + // field points to a string containing error details. + const char* const headerData; + const size_t headerLength; + // Include resolver's context. + void* userData; + protected: + IncludeResult& operator=(const IncludeResult&); + IncludeResult(); + }; + + // For both include methods below: + // + // Resolves an inclusion request by name, current source name, + // and include depth. + // On success, returns an IncludeResult containing the resolved name + // and content of the include. + // On failure, returns a nullptr, or an IncludeResult + // with an empty string for the headerName and error details in the + // header field. + // The Includer retains ownership of the contents + // of the returned IncludeResult value, and those contents must + // remain valid until the releaseInclude method is called on that + // IncludeResult object. + // + // Note "local" vs. "system" is not an "either/or": "local" is an + // extra thing to do over "system". Both might get called, as per + // the C++ specification. + + // For the "system" or <>-style includes; search the "system" paths. + virtual IncludeResult* includeSystem(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // For the "local"-only aspect of a "" include. Should not search in the + // "system" paths, because on returning a failure, the parser will + // call includeSystem() to look in the "system" locations. + virtual IncludeResult* includeLocal(const char* /*headerName*/, + const char* /*includerName*/, + size_t /*inclusionDepth*/) { return nullptr; } + + // Signals that the parser will no longer use the contents of the + // specified IncludeResult. + virtual void releaseInclude(IncludeResult*) = 0; + virtual ~Includer() {} + }; + + // Fail all Includer searches + class ForbidIncluder : public Includer { + public: + virtual void releaseInclude(IncludeResult*) override { } + }; + + bool parse(const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages, Includer&); + + bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages messages) + { + TShader::ForbidIncluder includer; + return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); + } + + // Equivalent to parse() without a default profile and without forcing defaults. + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); + } + + bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, + Includer& includer) + { + return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); + } + + // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string + // is not an officially supported or fully working path. + bool preprocess(const TBuiltInResource* builtInResources, + int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, EShMessages message, std::string* outputString, + Includer& includer); + + const char* getInfoLog(); + const char* getInfoDebugLog(); + EShLanguage getStage() const { return stage; } + TIntermediate* getIntermediate() const { return intermediate; } + +protected: + TPoolAllocator* pool; + EShLanguage stage; + TCompiler* compiler; + TIntermediate* intermediate; + TInfoSink* infoSink; + // strings and lengths follow the standard for glShaderSource: + // strings is an array of numStrings pointers to string data. + // lengths can be null, but if not it is an array of numStrings + // integers containing the length of the associated strings. + // if lengths is null or lengths[n] < 0 the associated strings[n] is + // assumed to be null-terminated. + // stringNames is the optional names for all the strings. If stringNames + // is null, then none of the strings has name. If a certain element in + // stringNames is null, then the corresponding string does not have name. + const char* const* strings; // explicit code to compile, see previous comment + const int* lengths; + const char* const* stringNames; + int numStrings; // size of the above arrays + const char* preamble; // string of implicit code to compile before the explicitly provided code + + // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. + std::string sourceEntryPointName; + + TEnvironment environment; + + friend class TProgram; + +private: + TShader& operator=(TShader&); +}; + +#ifndef GLSLANG_WEB + +// +// A reflection database and its interface, consistent with the OpenGL API reflection queries. +// + +// Data needed for just a single object at the granularity exchanged by the reflection API +class TObjectReflection { +public: + TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); + + const TType* getType() const { return type; } + int getBinding() const; + void dump() const; + static TObjectReflection badReflection() { return TObjectReflection(); } + + std::string name; + int offset; + int glDefineType; + int size; // data size in bytes for a block, array size for a (non-block) object that's an array + int index; + int counterIndex; + int numMembers; + int arrayStride; // stride of an array variable + int topLevelArrayStride; // stride of the top-level variable in a storage buffer member + EShLanguageMask stages; + +protected: + TObjectReflection() + : offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0), + topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr) + { + } + + const TType* type; +}; + +class TReflection; +class TIoMapper; +struct TVarEntryInfo; + +// Allows to customize the binding layout after linking. +// All used uniform variables will invoke at least validateBinding. +// If validateBinding returned true then the other resolveBinding, +// resolveSet, and resolveLocation are invoked to resolve the binding +// and descriptor set index respectively. +// +// Invocations happen in a particular order: +// 1) all shader inputs +// 2) all shader outputs +// 3) all uniforms with binding and set already defined +// 4) all uniforms with binding but no set defined +// 5) all uniforms with set but no binding defined +// 6) all uniforms with no binding and no set defined +// +// mapIO will use this resolver in two phases. The first +// phase is a notification phase, calling the corresponging +// notifiy callbacks, this phase ends with a call to endNotifications. +// Phase two starts directly after the call to endNotifications +// and calls all other callbacks to validate and to get the +// bindings, sets, locations, component and color indices. +// +// NOTE: that still limit checks are applied to bindings and sets +// and may result in an error. +class TIoMapResolver +{ +public: + virtual ~TIoMapResolver() {} + + // Should return true if the resulting/current binding would be okay. + // Basic idea is to do aliasing binding checks with this. + virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current binding should be overridden. + // Return -1 if the current binding (including no binding) should be kept. + virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current set should be overridden. + // Return -1 if the current set (including no set) should be kept. + virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return true if the resulting/current setup would be okay. + // Basic idea is to do aliasing checks and reject invalid semantic names. + virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current location should be overridden. + // Return -1 if the current location (including no location) should be kept. + virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current component index should be overridden. + // Return -1 if the current component index (including no index) should be kept. + virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Should return a value >= 0 if the current color index should be overridden. + // Return -1 if the current color index (including no index) should be kept. + virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a uniform variable + virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Notification of a in or out variable + virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; + // Called by mapIO when it starts its notify pass for the given stage + virtual void beginNotifications(EShLanguage stage) = 0; + // Called by mapIO when it has finished the notify pass + virtual void endNotifications(EShLanguage stage) = 0; + // Called by mipIO when it starts its resolve pass for the given stage + virtual void beginResolve(EShLanguage stage) = 0; + // Called by mapIO when it has finished the resolve pass + virtual void endResolve(EShLanguage stage) = 0; + // Called by mapIO when it starts its symbol collect for teh given stage + virtual void beginCollect(EShLanguage stage) = 0; + // Called by mapIO when it has finished the symbol collect + virtual void endCollect(EShLanguage stage) = 0; + // Called by TSlotCollector to resolve storage locations or bindings + virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by TSlotCollector to resolve resource locations or bindings + virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; + // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline + virtual void addStage(EShLanguage stage) = 0; +}; + +#endif // GLSLANG_WEB + +// Make one TProgram per set of shaders that will get linked together. Add all +// the shaders that are to be linked together. After calling shader.parse() +// for all shaders, call link(). +// +// N.B.: Destruct a linked program *before* destructing the shaders linked into it. +// +class TProgram { +public: + TProgram(); + virtual ~TProgram(); + void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } + std::list& getShaders(EShLanguage stage) { return stages[stage]; } + // Link Validation interface + bool link(EShMessages); + const char* getInfoLog(); + const char* getInfoDebugLog(); + + TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } + +#ifndef GLSLANG_WEB + + // Reflection Interface + + // call first, to do liveness analysis, index mapping, etc.; returns false on failure + bool buildReflection(int opts = EShReflectionDefault); + unsigned getLocalSize(int dim) const; // return dim'th local size + int getReflectionIndex(const char *name) const; + int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; + int getNumUniformVariables() const; + const TObjectReflection& getUniform(int index) const; + int getNumUniformBlocks() const; + const TObjectReflection& getUniformBlock(int index) const; + int getNumPipeInputs() const; + const TObjectReflection& getPipeInput(int index) const; + int getNumPipeOutputs() const; + const TObjectReflection& getPipeOutput(int index) const; + int getNumBufferVariables() const; + const TObjectReflection& getBufferVariable(int index) const; + int getNumBufferBlocks() const; + const TObjectReflection& getBufferBlock(int index) const; + int getNumAtomicCounters() const; + const TObjectReflection& getAtomicCounter(int index) const; + + // Legacy Reflection Interface - expressed in terms of above interface + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) + int getNumLiveUniformVariables() const { return getNumUniformVariables(); } + + // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) + int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); } + + // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) + int getNumLiveAttributes() const { return getNumPipeInputs(); } + + // can be used for glGetUniformIndices() + int getUniformIndex(const char *name) const { return getReflectionIndex(name); } + + int getPipeIOIndex(const char *name, const bool inOrOut) const + { return getReflectionPipeIOIndex(name, inOrOut); } + + // can be used for "name" part of glGetActiveUniform() + const char *getUniformName(int index) const { return getUniform(index).name.c_str(); } + + // returns the binding number + int getUniformBinding(int index) const { return getUniform(index).getBinding(); } + + // returns Shaders Stages where a Uniform is present + EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) + int getUniformBlockIndex(int index) const { return getUniform(index).index; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) + int getUniformType(int index) const { return getUniform(index).glDefineType; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) + int getUniformBufferOffset(int index) const { return getUniform(index).offset; } + + // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) + int getUniformArraySize(int index) const { return getUniform(index).size; } + + // returns a TType* + const TType *getUniformTType(int index) const { return getUniform(index).getType(); } + + // can be used for glGetActiveUniformBlockName() + const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); } + + // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) + int getUniformBlockSize(int index) const { return getUniformBlock(index).size; } + + // returns the block binding number + int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); } + + // returns block index of associated counter. + int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; } + + // returns a TType* + const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); } + + // can be used for glGetActiveAttrib() + const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); } + + // can be used for glGetActiveAttrib() + int getAttributeType(int index) const { return getPipeInput(index).glDefineType; } + + // returns a TType* + const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); } + + void dumpReflection(); + // I/O mapping: apply base offsets and map live unbound variables + // If resolver is not provided it uses the previous approach + // and respects auto assignment and offsets. + bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); +#endif + +protected: + bool linkStage(EShLanguage, EShMessages); + + TPoolAllocator* pool; + std::list stages[EShLangCount]; + TIntermediate* intermediate[EShLangCount]; + bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage + TInfoSink* infoSink; +#ifndef GLSLANG_WEB + TReflection* reflection; +#endif + bool linked; + +private: + TProgram(TProgram&); + TProgram& operator=(TProgram&); +}; + +} // end namespace glslang + +#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/ios/include/glslang/SPIRV/GLSL.ext.AMD.h b/ios/include/glslang/SPIRV/GLSL.ext.AMD.h new file mode 100644 index 00000000..009d2f1c --- /dev/null +++ b/ios/include/glslang/SPIRV/GLSL.ext.AMD.h @@ -0,0 +1,108 @@ +/* +** 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/ios/include/glslang/SPIRV/GLSL.ext.EXT.h b/ios/include/glslang/SPIRV/GLSL.ext.EXT.h new file mode 100644 index 00000000..40164b61 --- /dev/null +++ b/ios/include/glslang/SPIRV/GLSL.ext.EXT.h @@ -0,0 +1,39 @@ +/* +** 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"; + +#endif // #ifndef GLSLextEXT_H diff --git a/ios/include/glslang/SPIRV/GLSL.ext.KHR.h b/ios/include/glslang/SPIRV/GLSL.ext.KHR.h new file mode 100644 index 00000000..d783a8f2 --- /dev/null +++ b/ios/include/glslang/SPIRV/GLSL.ext.KHR.h @@ -0,0 +1,51 @@ +/* +** Copyright (c) 2014-2020 The Khronos Group Inc. +** 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 = 2; + +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"; +#endif // #ifndef GLSLextKHR_H diff --git a/ios/include/glslang/SPIRV/GLSL.ext.NV.h b/ios/include/glslang/SPIRV/GLSL.ext.NV.h new file mode 100644 index 00000000..50146da1 --- /dev/null +++ b/ios/include/glslang/SPIRV/GLSL.ext.NV.h @@ -0,0 +1,81 @@ +/* +** 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_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"; + +#endif // #ifndef GLSLextNV_H diff --git a/ios/include/glslang/SPIRV/GLSL.std.450.h b/ios/include/glslang/SPIRV/GLSL.std.450.h new file mode 100644 index 00000000..df31092b --- /dev/null +++ b/ios/include/glslang/SPIRV/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** 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/ios/include/glslang/SPIRV/GlslangToSpv.h b/ios/include/glslang/SPIRV/GlslangToSpv.h new file mode 100644 index 00000000..3907be43 --- /dev/null +++ b/ios/include/glslang/SPIRV/GlslangToSpv.h @@ -0,0 +1,61 @@ +// +// 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 + +#if defined(_MSC_VER) && _MSC_VER >= 1900 + #pragma warning(disable : 4464) // relative include path contains '..' +#endif + +#include "SpvTools.h" +#include "glslang/Include/intermediate.h" + +#include +#include + +#include "Logger.h" + +namespace glslang { + +void GetSpirvVersion(std::string&); +int GetSpirvGeneratorVersion(); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + SpvOptions* options = nullptr); +void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); +void OutputSpvBin(const std::vector& spirv, const char* baseName); +void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); + +} diff --git a/ios/include/glslang/SPIRV/Logger.h b/ios/include/glslang/SPIRV/Logger.h new file mode 100644 index 00000000..411367c0 --- /dev/null +++ b/ios/include/glslang/SPIRV/Logger.h @@ -0,0 +1,83 @@ +// +// 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 + +namespace spv { + +// A class for holding all SPIR-V build status messages, including +// missing/TBD functionalities, warnings, and errors. +class SpvBuildLogger { +public: + SpvBuildLogger() {} + +#ifdef GLSLANG_WEB + void tbdFunctionality(const std::string& f) { } + void missingFunctionality(const std::string& f) { } + void warning(const std::string& w) { } + void error(const std::string& e) { errors.push_back(e); } + std::string getAllMessages() { return ""; } +#else + + // 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; +#endif + +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/ios/include/glslang/SPIRV/NonSemanticDebugPrintf.h b/ios/include/glslang/SPIRV/NonSemanticDebugPrintf.h new file mode 100644 index 00000000..83796d75 --- /dev/null +++ b/ios/include/glslang/SPIRV/NonSemanticDebugPrintf.h @@ -0,0 +1,50 @@ +// 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/ios/include/glslang/SPIRV/SPVRemapper.h b/ios/include/glslang/SPIRV/SPVRemapper.h new file mode 100644 index 00000000..d6b9c346 --- /dev/null +++ b/ios/include/glslang/SPIRV/SPVRemapper.h @@ -0,0 +1,304 @@ +// +// 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 + +namespace spv { + +// MSVC defines __cplusplus as an older value, even when it supports almost all of 11. +// We handle that here by making our own symbol. +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700) +# define use_cpp11 1 +#endif + +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 + +#if !defined (use_cpp11) +#include +#include + +namespace spv { +class spirvbin_t : public spirvbin_base_t +{ +public: + spirvbin_t(int /*verbose = 0*/) { } + + void remap(std::vector& /*spv*/, unsigned int /*opts = 0*/) + { + printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n"); + exit(5); + } +}; + +} // namespace SPV + +#else // defined (use_cpp11) + +#include +#include +#include +#include +#include +#include +#include + +#include "spirv.hpp" +#include "spvIR.h" + +namespace spv { + +// class to hold SPIR-V binary data for remapping, DCE, and debug stripping +class 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, 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; + + 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 + + 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 // defined (use_cpp11) +#endif // SPIRVREMAPPER_H diff --git a/ios/include/glslang/SPIRV/SpvBuilder.h b/ios/include/glslang/SPIRV/SpvBuilder.h new file mode 100644 index 00000000..71b90d60 --- /dev/null +++ b/ios/include/glslang/SPIRV/SpvBuilder.h @@ -0,0 +1,838 @@ +// +// 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" +#include "spirv.hpp" +#include "spvIR.h" + +#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) + { + source = 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; + } + void setSourceFile(const std::string& file) + { + sourceFileStringId = getStringId(file); + } + 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 setEmitOpLines() { emitOpLines = true; } + 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; + } + + // Generate OpLine for non-filename-based #line directives (ie no filename + // seen yet): Log the current line, and if different than the last one, + // issue a new OpLine using the new line and current source file name. + void setLine(int line); + + // If filename null, generate OpLine for non-filename-based line directives, + // else do filename-based: Log the current line and file, and if different + // than the last one, issue a new OpLine using the new line and file + // name. + void setLine(int line, const char* filename); + // Low-level OpLine. See setLine() for a layered helper. + void addLine(Id fileName, int line, int column); + + // 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*); + 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 makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); + + // accelerationStructureNV type + Id makeAccelerationStructureType(); + // rayQueryEXT type + Id makeRayQueryType(); + + // 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; + int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } + int getNumTypeConstituents(Id typeId) const; + 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); } + + 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 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; } +#ifdef GLSLANG_WEB + bool isCooperativeMatrixType(Id typeId)const { return false; } +#else + bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } +#endif + 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)); } + + int getScalarTypeWidth(Id typeId) const + { + Id scalarTypeId = getScalarTypeId(typeId); + assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); + return module.getInstruction(scalarTypeId)->getImmediateOperand(0); + } + + int getTypeNumColumns(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeConstituents(typeId); + } + int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } + int getTypeNumRows(Id typeId) const + { + assert(isMatrixType(typeId)); + return getNumTypeComponents(getContainedTypeId(typeId)); + } + 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 makeBoolConstant(bool b, bool specConstant = false); + 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); + + // 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 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 addDecorationId(Id id, Decoration, Id idDecoration); + void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); + void addMemberDecoration(Id, unsigned int member, Decoration, const char*); + + // At the end of what block do the next create*() instructions go? + void setBuildPoint(Block* bp) { buildPoint = bp; } + Block* getBuildPoint() const { return buildPoint; } + + // 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, + const std::vector& paramTypes, const std::vector>& precisions, Block **entry = 0); + + // 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); + + // Generate all the code needed to finish up a function. + void leaveFunction(); + + // Create a discard. + void makeDiscard(); + + // Create a global or function local or IO variable. + Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); + + // 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::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 OpCooperativeMatrixLengthNV instruction + Id createCooperativeMatrixLength(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); + + // 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(); + + // 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(); } +#ifdef GLSLANG_WEB + void clear() { } + bool isVolatile() const { return false; } + CoherentFlags operator |=(const CoherentFlags &other) { return *this; } +#else + bool isVolatile() const { return volatil; } + 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; + + void clear() { + coherent = 0; + devicecoherent = 0; + queuefamilycoherent = 0; + workgroupcoherent = 0; + subgroupcoherent = 0; + shadercallcoherent = 0; + nonprivate = 0; + volatil = 0; + isImage = 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; + return *this; + } +#endif + }; + 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, 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 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(); + + // Prune unreachable blocks in the CFG and remove unneeded decorations. + void postProcessCFG(); + +#ifndef GLSLANG_WEB + // 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); +#endif + + void dump(std::vector&) const; + + void createBranch(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; } + + protected: + Id makeIntConstant(Id typeId, unsigned value, bool specConstant); + Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); + 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; + void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; + spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) + const; + + unsigned int spvVersion; // the version of SPIR-V to emit in the header + SourceLanguage source; + int sourceVersion; + spv::Id sourceFileStringId; + std::string sourceText; + int currentLine; + const char* currentFile; + bool emitOpLines; + 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; + AccessChain accessChain; + + // special blocks of instructions for output + std::vector > strings; + std::vector > imports; + std::vector > entryPoints; + std::vector > executionModes; + std::vector > names; + std::vector > 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; + + // 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; + + // The stream for outputting warnings and errors. + SpvBuildLogger* logger; +}; // end Builder class + +}; // end spv namespace + +#endif // SpvBuilder_H diff --git a/ios/include/glslang/SPIRV/SpvTools.h b/ios/include/glslang/SPIRV/SpvTools.h new file mode 100644 index 00000000..59c914da --- /dev/null +++ b/ios/include/glslang/SPIRV/SpvTools.h @@ -0,0 +1,82 @@ +// +// 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 + +#ifdef ENABLE_OPT +#include +#include +#endif + +#include "glslang/MachineIndependent/localintermediate.h" +#include "Logger.h" + +namespace glslang { + +struct SpvOptions { + SpvOptions() : generateDebugInfo(false), disableOptimizer(true), + optimizeSize(false), disassemble(false), validate(false) { } + bool generateDebugInfo; + bool disableOptimizer; + bool optimizeSize; + bool disassemble; + bool validate; +}; + +#ifdef ENABLE_OPT + +// Use the SPIRV-Tools disassembler to print SPIR-V. +void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); + +// Apply the SPIRV-Tools validator to generated SPIR-V. +void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, bool prelegalization); + +// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of +// legalizing HLSL SPIR-V. +void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector& spirv, + spv::SpvBuildLogger*, const SpvOptions*); + +#endif + +} // end namespace glslang + +#endif // GLSLANG_SPV_TOOLS_H diff --git a/ios/include/glslang/SPIRV/bitutils.h b/ios/include/glslang/SPIRV/bitutils.h new file mode 100644 index 00000000..22e44cec --- /dev/null +++ b/ios/include/glslang/SPIRV/bitutils.h @@ -0,0 +1,81 @@ +// 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/ios/include/glslang/SPIRV/disassemble.h b/ios/include/glslang/SPIRV/disassemble.h new file mode 100644 index 00000000..b6a46357 --- /dev/null +++ b/ios/include/glslang/SPIRV/disassemble.h @@ -0,0 +1,53 @@ +// +// 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 + +namespace spv { + + // disassemble with glslang custom disassembler + void Disassemble(std::ostream& out, const std::vector&); + +} // end namespace spv + +#endif // disassembler_H diff --git a/ios/include/glslang/SPIRV/doc.h b/ios/include/glslang/SPIRV/doc.h new file mode 100644 index 00000000..293256a2 --- /dev/null +++ b/ios/include/glslang/SPIRV/doc.h @@ -0,0 +1,258 @@ +// +// 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, + 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, + + 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(0) { } + const char* desc; +}; + +// Parameterize a set of enumerants that form an enum +class EnumDefinition : public EnumParameters { +public: + EnumDefinition() : + ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { } + 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: + int typePresent : 1; + int 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/ios/include/glslang/SPIRV/hex_float.h b/ios/include/glslang/SPIRV/hex_float.h new file mode 100644 index 00000000..8be8e9f7 --- /dev/null +++ b/ios/include/glslang/SPIRV/hex_float.h @@ -0,0 +1,1078 @@ +// 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 + +#if defined(_MSC_VER) && _MSC_VER < 1800 +namespace std { +bool isnan(double f) +{ + return ::_isnan(f) != 0; +} +bool isinf(double f) +{ + return ::_finite(f) == 0; +} +} +#endif + +#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/ios/include/glslang/SPIRV/spirv.hpp b/ios/include/glslang/SPIRV/spirv.hpp new file mode 100644 index 00000000..dae36cf2 --- /dev/null +++ b/ios/include/glslang/SPIRV/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-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. + +// 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 +// +// - 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 +// +// 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 0x10500 +#define SPV_REVISION 3 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +static const unsigned int Revision = 3; +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, + 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, + 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, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + 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, + 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, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + 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, + 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, + 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, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + 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, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + 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, + 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, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + 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, + 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, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + 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, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + 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, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + 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, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +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 { + 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, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +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 { + 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, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + 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, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + 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, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +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 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, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + 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, + 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, + 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, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +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 OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpTypeRayQueryProvisionalKHR: *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 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 OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *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 OpTypeAccelerationStructureNV: *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 OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *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 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 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; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/ios/include/glslang/SPIRV/spvIR.h b/ios/include/glslang/SPIRV/spvIR.h new file mode 100644 index 00000000..6523035e --- /dev/null +++ b/ios/include/glslang/SPIRV/spvIR.h @@ -0,0 +1,485 @@ +// +// 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 + +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 addIdOperand(Id id) { + operands.push_back(id); + idOperand.push_back(true); + } + 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; + char* wordString = (char*)&word; + char* wordPtr = wordString; + int charCount = 0; + char c; + do { + c = *(str++); + *(wordPtr++) = c; + ++charCount; + if (charCount == 4) { + addImmediateOperand(word); + wordPtr = wordString; + charCount = 0; + } + } while (c != 0); + + // deal with partial last word + if (charCount > 0) { + // pad with 0s + for (; charCount < 4; ++charCount) + *(wordPtr++) = 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]); + } + +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. +// + +class Block { +public: + Block(Id id, Function& parent); + virtual ~Block() + { + } + + Id getId() { return instructions.front()->getResultId(); } + + Function& getParent() const { return parent; } + 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; } + const std::vector >& getInstructions() const { + 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 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 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, 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(); } + + void setImplicitThis() { implicitThis = true; } + bool hasImplicitThis() const { return implicitThis; } + + void dump(std::vector& out) const + { + // 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); + } + +protected: + Function(const Function&); + Function& operator=(Function&); + + Module& parent; + 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 +}; + +// +// 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, Module& parent) + : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) +{ + // OpFunction + 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); + } +} + +__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 diff --git a/ios/include/spirv_cross/GLSL.std.450.h b/ios/include/spirv_cross/GLSL.std.450.h new file mode 100644 index 00000000..54cc00e9 --- /dev/null +++ b/ios/include/spirv_cross/GLSL.std.450.h @@ -0,0 +1,131 @@ +/* +** 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 = 3; + +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/ios/include/spirv_cross/spirv.h b/ios/include/spirv_cross/spirv.h new file mode 100644 index 00000000..92b34c38 --- /dev/null +++ b/ios/include/spirv_cross/spirv.h @@ -0,0 +1,2104 @@ +/* +** Copyright (c) 2014-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. +*/ + +/* +** 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 +** +** - 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 +** +** 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_H +#define spirv_H + +typedef unsigned int SpvId; + +#define SPV_VERSION 0x10500 +#define SPV_REVISION 1 + +static const unsigned int SpvMagicNumber = 0x07230203; +static const unsigned int SpvVersion = 0x00010500; +static const unsigned int SpvRevision = 1; +static const unsigned int SpvOpCodeMask = 0xffff; +static const unsigned int SpvWordCountShift = 16; + +typedef enum SpvSourceLanguage_ { + SpvSourceLanguageUnknown = 0, + SpvSourceLanguageESSL = 1, + SpvSourceLanguageGLSL = 2, + SpvSourceLanguageOpenCL_C = 3, + SpvSourceLanguageOpenCL_CPP = 4, + SpvSourceLanguageHLSL = 5, + SpvSourceLanguageMax = 0x7fffffff, +} SpvSourceLanguage; + +typedef enum SpvExecutionModel_ { + SpvExecutionModelVertex = 0, + SpvExecutionModelTessellationControl = 1, + SpvExecutionModelTessellationEvaluation = 2, + SpvExecutionModelGeometry = 3, + SpvExecutionModelFragment = 4, + SpvExecutionModelGLCompute = 5, + SpvExecutionModelKernel = 6, + SpvExecutionModelTaskNV = 5267, + SpvExecutionModelMeshNV = 5268, + SpvExecutionModelRayGenerationKHR = 5313, + SpvExecutionModelRayGenerationNV = 5313, + SpvExecutionModelIntersectionKHR = 5314, + SpvExecutionModelIntersectionNV = 5314, + SpvExecutionModelAnyHitKHR = 5315, + SpvExecutionModelAnyHitNV = 5315, + SpvExecutionModelClosestHitKHR = 5316, + SpvExecutionModelClosestHitNV = 5316, + SpvExecutionModelMissKHR = 5317, + SpvExecutionModelMissNV = 5317, + SpvExecutionModelCallableKHR = 5318, + SpvExecutionModelCallableNV = 5318, + SpvExecutionModelMax = 0x7fffffff, +} SpvExecutionModel; + +typedef enum SpvAddressingModel_ { + SpvAddressingModelLogical = 0, + SpvAddressingModelPhysical32 = 1, + SpvAddressingModelPhysical64 = 2, + SpvAddressingModelPhysicalStorageBuffer64 = 5348, + SpvAddressingModelPhysicalStorageBuffer64EXT = 5348, + SpvAddressingModelMax = 0x7fffffff, +} SpvAddressingModel; + +typedef enum SpvMemoryModel_ { + SpvMemoryModelSimple = 0, + SpvMemoryModelGLSL450 = 1, + SpvMemoryModelOpenCL = 2, + SpvMemoryModelVulkan = 3, + SpvMemoryModelVulkanKHR = 3, + SpvMemoryModelMax = 0x7fffffff, +} SpvMemoryModel; + +typedef enum SpvExecutionMode_ { + SpvExecutionModeInvocations = 0, + SpvExecutionModeSpacingEqual = 1, + SpvExecutionModeSpacingFractionalEven = 2, + SpvExecutionModeSpacingFractionalOdd = 3, + SpvExecutionModeVertexOrderCw = 4, + SpvExecutionModeVertexOrderCcw = 5, + SpvExecutionModePixelCenterInteger = 6, + SpvExecutionModeOriginUpperLeft = 7, + SpvExecutionModeOriginLowerLeft = 8, + SpvExecutionModeEarlyFragmentTests = 9, + SpvExecutionModePointMode = 10, + SpvExecutionModeXfb = 11, + SpvExecutionModeDepthReplacing = 12, + SpvExecutionModeDepthGreater = 14, + SpvExecutionModeDepthLess = 15, + SpvExecutionModeDepthUnchanged = 16, + SpvExecutionModeLocalSize = 17, + SpvExecutionModeLocalSizeHint = 18, + SpvExecutionModeInputPoints = 19, + SpvExecutionModeInputLines = 20, + SpvExecutionModeInputLinesAdjacency = 21, + SpvExecutionModeTriangles = 22, + SpvExecutionModeInputTrianglesAdjacency = 23, + SpvExecutionModeQuads = 24, + SpvExecutionModeIsolines = 25, + SpvExecutionModeOutputVertices = 26, + SpvExecutionModeOutputPoints = 27, + SpvExecutionModeOutputLineStrip = 28, + SpvExecutionModeOutputTriangleStrip = 29, + SpvExecutionModeVecTypeHint = 30, + SpvExecutionModeContractionOff = 31, + SpvExecutionModeInitializer = 33, + SpvExecutionModeFinalizer = 34, + SpvExecutionModeSubgroupSize = 35, + SpvExecutionModeSubgroupsPerWorkgroup = 36, + SpvExecutionModeSubgroupsPerWorkgroupId = 37, + SpvExecutionModeLocalSizeId = 38, + SpvExecutionModeLocalSizeHintId = 39, + SpvExecutionModePostDepthCoverage = 4446, + SpvExecutionModeDenormPreserve = 4459, + SpvExecutionModeDenormFlushToZero = 4460, + SpvExecutionModeSignedZeroInfNanPreserve = 4461, + SpvExecutionModeRoundingModeRTE = 4462, + SpvExecutionModeRoundingModeRTZ = 4463, + SpvExecutionModeStencilRefReplacingEXT = 5027, + SpvExecutionModeOutputLinesNV = 5269, + SpvExecutionModeOutputPrimitivesNV = 5270, + SpvExecutionModeDerivativeGroupQuadsNV = 5289, + SpvExecutionModeDerivativeGroupLinearNV = 5290, + SpvExecutionModeOutputTrianglesNV = 5298, + SpvExecutionModePixelInterlockOrderedEXT = 5366, + SpvExecutionModePixelInterlockUnorderedEXT = 5367, + SpvExecutionModeSampleInterlockOrderedEXT = 5368, + SpvExecutionModeSampleInterlockUnorderedEXT = 5369, + SpvExecutionModeShadingRateInterlockOrderedEXT = 5370, + SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371, + SpvExecutionModeMax = 0x7fffffff, +} SpvExecutionMode; + +typedef enum SpvStorageClass_ { + SpvStorageClassUniformConstant = 0, + SpvStorageClassInput = 1, + SpvStorageClassUniform = 2, + SpvStorageClassOutput = 3, + SpvStorageClassWorkgroup = 4, + SpvStorageClassCrossWorkgroup = 5, + SpvStorageClassPrivate = 6, + SpvStorageClassFunction = 7, + SpvStorageClassGeneric = 8, + SpvStorageClassPushConstant = 9, + SpvStorageClassAtomicCounter = 10, + SpvStorageClassImage = 11, + SpvStorageClassStorageBuffer = 12, + SpvStorageClassCallableDataKHR = 5328, + SpvStorageClassCallableDataNV = 5328, + SpvStorageClassIncomingCallableDataKHR = 5329, + SpvStorageClassIncomingCallableDataNV = 5329, + SpvStorageClassRayPayloadKHR = 5338, + SpvStorageClassRayPayloadNV = 5338, + SpvStorageClassHitAttributeKHR = 5339, + SpvStorageClassHitAttributeNV = 5339, + SpvStorageClassIncomingRayPayloadKHR = 5342, + SpvStorageClassIncomingRayPayloadNV = 5342, + SpvStorageClassShaderRecordBufferKHR = 5343, + SpvStorageClassShaderRecordBufferNV = 5343, + SpvStorageClassPhysicalStorageBuffer = 5349, + SpvStorageClassPhysicalStorageBufferEXT = 5349, + SpvStorageClassMax = 0x7fffffff, +} SpvStorageClass; + +typedef enum SpvDim_ { + SpvDim1D = 0, + SpvDim2D = 1, + SpvDim3D = 2, + SpvDimCube = 3, + SpvDimRect = 4, + SpvDimBuffer = 5, + SpvDimSubpassData = 6, + SpvDimMax = 0x7fffffff, +} SpvDim; + +typedef enum SpvSamplerAddressingMode_ { + SpvSamplerAddressingModeNone = 0, + SpvSamplerAddressingModeClampToEdge = 1, + SpvSamplerAddressingModeClamp = 2, + SpvSamplerAddressingModeRepeat = 3, + SpvSamplerAddressingModeRepeatMirrored = 4, + SpvSamplerAddressingModeMax = 0x7fffffff, +} SpvSamplerAddressingMode; + +typedef enum SpvSamplerFilterMode_ { + SpvSamplerFilterModeNearest = 0, + SpvSamplerFilterModeLinear = 1, + SpvSamplerFilterModeMax = 0x7fffffff, +} SpvSamplerFilterMode; + +typedef enum SpvImageFormat_ { + SpvImageFormatUnknown = 0, + SpvImageFormatRgba32f = 1, + SpvImageFormatRgba16f = 2, + SpvImageFormatR32f = 3, + SpvImageFormatRgba8 = 4, + SpvImageFormatRgba8Snorm = 5, + SpvImageFormatRg32f = 6, + SpvImageFormatRg16f = 7, + SpvImageFormatR11fG11fB10f = 8, + SpvImageFormatR16f = 9, + SpvImageFormatRgba16 = 10, + SpvImageFormatRgb10A2 = 11, + SpvImageFormatRg16 = 12, + SpvImageFormatRg8 = 13, + SpvImageFormatR16 = 14, + SpvImageFormatR8 = 15, + SpvImageFormatRgba16Snorm = 16, + SpvImageFormatRg16Snorm = 17, + SpvImageFormatRg8Snorm = 18, + SpvImageFormatR16Snorm = 19, + SpvImageFormatR8Snorm = 20, + SpvImageFormatRgba32i = 21, + SpvImageFormatRgba16i = 22, + SpvImageFormatRgba8i = 23, + SpvImageFormatR32i = 24, + SpvImageFormatRg32i = 25, + SpvImageFormatRg16i = 26, + SpvImageFormatRg8i = 27, + SpvImageFormatR16i = 28, + SpvImageFormatR8i = 29, + SpvImageFormatRgba32ui = 30, + SpvImageFormatRgba16ui = 31, + SpvImageFormatRgba8ui = 32, + SpvImageFormatR32ui = 33, + SpvImageFormatRgb10a2ui = 34, + SpvImageFormatRg32ui = 35, + SpvImageFormatRg16ui = 36, + SpvImageFormatRg8ui = 37, + SpvImageFormatR16ui = 38, + SpvImageFormatR8ui = 39, + SpvImageFormatMax = 0x7fffffff, +} SpvImageFormat; + +typedef enum SpvImageChannelOrder_ { + SpvImageChannelOrderR = 0, + SpvImageChannelOrderA = 1, + SpvImageChannelOrderRG = 2, + SpvImageChannelOrderRA = 3, + SpvImageChannelOrderRGB = 4, + SpvImageChannelOrderRGBA = 5, + SpvImageChannelOrderBGRA = 6, + SpvImageChannelOrderARGB = 7, + SpvImageChannelOrderIntensity = 8, + SpvImageChannelOrderLuminance = 9, + SpvImageChannelOrderRx = 10, + SpvImageChannelOrderRGx = 11, + SpvImageChannelOrderRGBx = 12, + SpvImageChannelOrderDepth = 13, + SpvImageChannelOrderDepthStencil = 14, + SpvImageChannelOrdersRGB = 15, + SpvImageChannelOrdersRGBx = 16, + SpvImageChannelOrdersRGBA = 17, + SpvImageChannelOrdersBGRA = 18, + SpvImageChannelOrderABGR = 19, + SpvImageChannelOrderMax = 0x7fffffff, +} SpvImageChannelOrder; + +typedef enum SpvImageChannelDataType_ { + SpvImageChannelDataTypeSnormInt8 = 0, + SpvImageChannelDataTypeSnormInt16 = 1, + SpvImageChannelDataTypeUnormInt8 = 2, + SpvImageChannelDataTypeUnormInt16 = 3, + SpvImageChannelDataTypeUnormShort565 = 4, + SpvImageChannelDataTypeUnormShort555 = 5, + SpvImageChannelDataTypeUnormInt101010 = 6, + SpvImageChannelDataTypeSignedInt8 = 7, + SpvImageChannelDataTypeSignedInt16 = 8, + SpvImageChannelDataTypeSignedInt32 = 9, + SpvImageChannelDataTypeUnsignedInt8 = 10, + SpvImageChannelDataTypeUnsignedInt16 = 11, + SpvImageChannelDataTypeUnsignedInt32 = 12, + SpvImageChannelDataTypeHalfFloat = 13, + SpvImageChannelDataTypeFloat = 14, + SpvImageChannelDataTypeUnormInt24 = 15, + SpvImageChannelDataTypeUnormInt101010_2 = 16, + SpvImageChannelDataTypeMax = 0x7fffffff, +} SpvImageChannelDataType; + +typedef enum SpvImageOperandsShift_ { + SpvImageOperandsBiasShift = 0, + SpvImageOperandsLodShift = 1, + SpvImageOperandsGradShift = 2, + SpvImageOperandsConstOffsetShift = 3, + SpvImageOperandsOffsetShift = 4, + SpvImageOperandsConstOffsetsShift = 5, + SpvImageOperandsSampleShift = 6, + SpvImageOperandsMinLodShift = 7, + SpvImageOperandsMakeTexelAvailableShift = 8, + SpvImageOperandsMakeTexelAvailableKHRShift = 8, + SpvImageOperandsMakeTexelVisibleShift = 9, + SpvImageOperandsMakeTexelVisibleKHRShift = 9, + SpvImageOperandsNonPrivateTexelShift = 10, + SpvImageOperandsNonPrivateTexelKHRShift = 10, + SpvImageOperandsVolatileTexelShift = 11, + SpvImageOperandsVolatileTexelKHRShift = 11, + SpvImageOperandsSignExtendShift = 12, + SpvImageOperandsZeroExtendShift = 13, + SpvImageOperandsMax = 0x7fffffff, +} SpvImageOperandsShift; + +typedef enum SpvImageOperandsMask_ { + SpvImageOperandsMaskNone = 0, + SpvImageOperandsBiasMask = 0x00000001, + SpvImageOperandsLodMask = 0x00000002, + SpvImageOperandsGradMask = 0x00000004, + SpvImageOperandsConstOffsetMask = 0x00000008, + SpvImageOperandsOffsetMask = 0x00000010, + SpvImageOperandsConstOffsetsMask = 0x00000020, + SpvImageOperandsSampleMask = 0x00000040, + SpvImageOperandsMinLodMask = 0x00000080, + SpvImageOperandsMakeTexelAvailableMask = 0x00000100, + SpvImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + SpvImageOperandsMakeTexelVisibleMask = 0x00000200, + SpvImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + SpvImageOperandsNonPrivateTexelMask = 0x00000400, + SpvImageOperandsNonPrivateTexelKHRMask = 0x00000400, + SpvImageOperandsVolatileTexelMask = 0x00000800, + SpvImageOperandsVolatileTexelKHRMask = 0x00000800, + SpvImageOperandsSignExtendMask = 0x00001000, + SpvImageOperandsZeroExtendMask = 0x00002000, +} SpvImageOperandsMask; + +typedef enum SpvFPFastMathModeShift_ { + SpvFPFastMathModeNotNaNShift = 0, + SpvFPFastMathModeNotInfShift = 1, + SpvFPFastMathModeNSZShift = 2, + SpvFPFastMathModeAllowRecipShift = 3, + SpvFPFastMathModeFastShift = 4, + SpvFPFastMathModeMax = 0x7fffffff, +} SpvFPFastMathModeShift; + +typedef enum SpvFPFastMathModeMask_ { + SpvFPFastMathModeMaskNone = 0, + SpvFPFastMathModeNotNaNMask = 0x00000001, + SpvFPFastMathModeNotInfMask = 0x00000002, + SpvFPFastMathModeNSZMask = 0x00000004, + SpvFPFastMathModeAllowRecipMask = 0x00000008, + SpvFPFastMathModeFastMask = 0x00000010, +} SpvFPFastMathModeMask; + +typedef enum SpvFPRoundingMode_ { + SpvFPRoundingModeRTE = 0, + SpvFPRoundingModeRTZ = 1, + SpvFPRoundingModeRTP = 2, + SpvFPRoundingModeRTN = 3, + SpvFPRoundingModeMax = 0x7fffffff, +} SpvFPRoundingMode; + +typedef enum SpvLinkageType_ { + SpvLinkageTypeExport = 0, + SpvLinkageTypeImport = 1, + SpvLinkageTypeMax = 0x7fffffff, +} SpvLinkageType; + +typedef enum SpvAccessQualifier_ { + SpvAccessQualifierReadOnly = 0, + SpvAccessQualifierWriteOnly = 1, + SpvAccessQualifierReadWrite = 2, + SpvAccessQualifierMax = 0x7fffffff, +} SpvAccessQualifier; + +typedef enum SpvFunctionParameterAttribute_ { + SpvFunctionParameterAttributeZext = 0, + SpvFunctionParameterAttributeSext = 1, + SpvFunctionParameterAttributeByVal = 2, + SpvFunctionParameterAttributeSret = 3, + SpvFunctionParameterAttributeNoAlias = 4, + SpvFunctionParameterAttributeNoCapture = 5, + SpvFunctionParameterAttributeNoWrite = 6, + SpvFunctionParameterAttributeNoReadWrite = 7, + SpvFunctionParameterAttributeMax = 0x7fffffff, +} SpvFunctionParameterAttribute; + +typedef enum SpvDecoration_ { + SpvDecorationRelaxedPrecision = 0, + SpvDecorationSpecId = 1, + SpvDecorationBlock = 2, + SpvDecorationBufferBlock = 3, + SpvDecorationRowMajor = 4, + SpvDecorationColMajor = 5, + SpvDecorationArrayStride = 6, + SpvDecorationMatrixStride = 7, + SpvDecorationGLSLShared = 8, + SpvDecorationGLSLPacked = 9, + SpvDecorationCPacked = 10, + SpvDecorationBuiltIn = 11, + SpvDecorationNoPerspective = 13, + SpvDecorationFlat = 14, + SpvDecorationPatch = 15, + SpvDecorationCentroid = 16, + SpvDecorationSample = 17, + SpvDecorationInvariant = 18, + SpvDecorationRestrict = 19, + SpvDecorationAliased = 20, + SpvDecorationVolatile = 21, + SpvDecorationConstant = 22, + SpvDecorationCoherent = 23, + SpvDecorationNonWritable = 24, + SpvDecorationNonReadable = 25, + SpvDecorationUniform = 26, + SpvDecorationUniformId = 27, + SpvDecorationSaturatedConversion = 28, + SpvDecorationStream = 29, + SpvDecorationLocation = 30, + SpvDecorationComponent = 31, + SpvDecorationIndex = 32, + SpvDecorationBinding = 33, + SpvDecorationDescriptorSet = 34, + SpvDecorationOffset = 35, + SpvDecorationXfbBuffer = 36, + SpvDecorationXfbStride = 37, + SpvDecorationFuncParamAttr = 38, + SpvDecorationFPRoundingMode = 39, + SpvDecorationFPFastMathMode = 40, + SpvDecorationLinkageAttributes = 41, + SpvDecorationNoContraction = 42, + SpvDecorationInputAttachmentIndex = 43, + SpvDecorationAlignment = 44, + SpvDecorationMaxByteOffset = 45, + SpvDecorationAlignmentId = 46, + SpvDecorationMaxByteOffsetId = 47, + SpvDecorationNoSignedWrap = 4469, + SpvDecorationNoUnsignedWrap = 4470, + SpvDecorationExplicitInterpAMD = 4999, + SpvDecorationOverrideCoverageNV = 5248, + SpvDecorationPassthroughNV = 5250, + SpvDecorationViewportRelativeNV = 5252, + SpvDecorationSecondaryViewportRelativeNV = 5256, + SpvDecorationPerPrimitiveNV = 5271, + SpvDecorationPerViewNV = 5272, + SpvDecorationPerTaskNV = 5273, + SpvDecorationPerVertexNV = 5285, + SpvDecorationNonUniform = 5300, + SpvDecorationNonUniformEXT = 5300, + SpvDecorationRestrictPointer = 5355, + SpvDecorationRestrictPointerEXT = 5355, + SpvDecorationAliasedPointer = 5356, + SpvDecorationAliasedPointerEXT = 5356, + SpvDecorationCounterBuffer = 5634, + SpvDecorationHlslCounterBufferGOOGLE = 5634, + SpvDecorationHlslSemanticGOOGLE = 5635, + SpvDecorationUserSemantic = 5635, + SpvDecorationUserTypeGOOGLE = 5636, + SpvDecorationMax = 0x7fffffff, +} SpvDecoration; + +typedef enum SpvBuiltIn_ { + SpvBuiltInPosition = 0, + SpvBuiltInPointSize = 1, + SpvBuiltInClipDistance = 3, + SpvBuiltInCullDistance = 4, + SpvBuiltInVertexId = 5, + SpvBuiltInInstanceId = 6, + SpvBuiltInPrimitiveId = 7, + SpvBuiltInInvocationId = 8, + SpvBuiltInLayer = 9, + SpvBuiltInViewportIndex = 10, + SpvBuiltInTessLevelOuter = 11, + SpvBuiltInTessLevelInner = 12, + SpvBuiltInTessCoord = 13, + SpvBuiltInPatchVertices = 14, + SpvBuiltInFragCoord = 15, + SpvBuiltInPointCoord = 16, + SpvBuiltInFrontFacing = 17, + SpvBuiltInSampleId = 18, + SpvBuiltInSamplePosition = 19, + SpvBuiltInSampleMask = 20, + SpvBuiltInFragDepth = 22, + SpvBuiltInHelperInvocation = 23, + SpvBuiltInNumWorkgroups = 24, + SpvBuiltInWorkgroupSize = 25, + SpvBuiltInWorkgroupId = 26, + SpvBuiltInLocalInvocationId = 27, + SpvBuiltInGlobalInvocationId = 28, + SpvBuiltInLocalInvocationIndex = 29, + SpvBuiltInWorkDim = 30, + SpvBuiltInGlobalSize = 31, + SpvBuiltInEnqueuedWorkgroupSize = 32, + SpvBuiltInGlobalOffset = 33, + SpvBuiltInGlobalLinearId = 34, + SpvBuiltInSubgroupSize = 36, + SpvBuiltInSubgroupMaxSize = 37, + SpvBuiltInNumSubgroups = 38, + SpvBuiltInNumEnqueuedSubgroups = 39, + SpvBuiltInSubgroupId = 40, + SpvBuiltInSubgroupLocalInvocationId = 41, + SpvBuiltInVertexIndex = 42, + SpvBuiltInInstanceIndex = 43, + SpvBuiltInSubgroupEqMask = 4416, + SpvBuiltInSubgroupEqMaskKHR = 4416, + SpvBuiltInSubgroupGeMask = 4417, + SpvBuiltInSubgroupGeMaskKHR = 4417, + SpvBuiltInSubgroupGtMask = 4418, + SpvBuiltInSubgroupGtMaskKHR = 4418, + SpvBuiltInSubgroupLeMask = 4419, + SpvBuiltInSubgroupLeMaskKHR = 4419, + SpvBuiltInSubgroupLtMask = 4420, + SpvBuiltInSubgroupLtMaskKHR = 4420, + SpvBuiltInBaseVertex = 4424, + SpvBuiltInBaseInstance = 4425, + SpvBuiltInDrawIndex = 4426, + SpvBuiltInDeviceIndex = 4438, + SpvBuiltInViewIndex = 4440, + SpvBuiltInBaryCoordNoPerspAMD = 4992, + SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993, + SpvBuiltInBaryCoordNoPerspSampleAMD = 4994, + SpvBuiltInBaryCoordSmoothAMD = 4995, + SpvBuiltInBaryCoordSmoothCentroidAMD = 4996, + SpvBuiltInBaryCoordSmoothSampleAMD = 4997, + SpvBuiltInBaryCoordPullModelAMD = 4998, + SpvBuiltInFragStencilRefEXT = 5014, + SpvBuiltInViewportMaskNV = 5253, + SpvBuiltInSecondaryPositionNV = 5257, + SpvBuiltInSecondaryViewportMaskNV = 5258, + SpvBuiltInPositionPerViewNV = 5261, + SpvBuiltInViewportMaskPerViewNV = 5262, + SpvBuiltInFullyCoveredEXT = 5264, + SpvBuiltInTaskCountNV = 5274, + SpvBuiltInPrimitiveCountNV = 5275, + SpvBuiltInPrimitiveIndicesNV = 5276, + SpvBuiltInClipDistancePerViewNV = 5277, + SpvBuiltInCullDistancePerViewNV = 5278, + SpvBuiltInLayerPerViewNV = 5279, + SpvBuiltInMeshViewCountNV = 5280, + SpvBuiltInMeshViewIndicesNV = 5281, + SpvBuiltInBaryCoordNV = 5286, + SpvBuiltInBaryCoordNoPerspNV = 5287, + SpvBuiltInFragSizeEXT = 5292, + SpvBuiltInFragmentSizeNV = 5292, + SpvBuiltInFragInvocationCountEXT = 5293, + SpvBuiltInInvocationsPerPixelNV = 5293, + SpvBuiltInLaunchIdKHR = 5319, + SpvBuiltInLaunchIdNV = 5319, + SpvBuiltInLaunchSizeKHR = 5320, + SpvBuiltInLaunchSizeNV = 5320, + SpvBuiltInWorldRayOriginKHR = 5321, + SpvBuiltInWorldRayOriginNV = 5321, + SpvBuiltInWorldRayDirectionKHR = 5322, + SpvBuiltInWorldRayDirectionNV = 5322, + SpvBuiltInObjectRayOriginKHR = 5323, + SpvBuiltInObjectRayOriginNV = 5323, + SpvBuiltInObjectRayDirectionKHR = 5324, + SpvBuiltInObjectRayDirectionNV = 5324, + SpvBuiltInRayTminKHR = 5325, + SpvBuiltInRayTminNV = 5325, + SpvBuiltInRayTmaxKHR = 5326, + SpvBuiltInRayTmaxNV = 5326, + SpvBuiltInInstanceCustomIndexKHR = 5327, + SpvBuiltInInstanceCustomIndexNV = 5327, + SpvBuiltInObjectToWorldKHR = 5330, + SpvBuiltInObjectToWorldNV = 5330, + SpvBuiltInWorldToObjectKHR = 5331, + SpvBuiltInWorldToObjectNV = 5331, + SpvBuiltInHitTKHR = 5332, + SpvBuiltInHitTNV = 5332, + SpvBuiltInHitKindKHR = 5333, + SpvBuiltInHitKindNV = 5333, + SpvBuiltInIncomingRayFlagsKHR = 5351, + SpvBuiltInIncomingRayFlagsNV = 5351, + SpvBuiltInRayGeometryIndexKHR = 5352, + SpvBuiltInWarpsPerSMNV = 5374, + SpvBuiltInSMCountNV = 5375, + SpvBuiltInWarpIDNV = 5376, + SpvBuiltInSMIDNV = 5377, + SpvBuiltInMax = 0x7fffffff, +} SpvBuiltIn; + +typedef enum SpvSelectionControlShift_ { + SpvSelectionControlFlattenShift = 0, + SpvSelectionControlDontFlattenShift = 1, + SpvSelectionControlMax = 0x7fffffff, +} SpvSelectionControlShift; + +typedef enum SpvSelectionControlMask_ { + SpvSelectionControlMaskNone = 0, + SpvSelectionControlFlattenMask = 0x00000001, + SpvSelectionControlDontFlattenMask = 0x00000002, +} SpvSelectionControlMask; + +typedef enum SpvLoopControlShift_ { + SpvLoopControlUnrollShift = 0, + SpvLoopControlDontUnrollShift = 1, + SpvLoopControlDependencyInfiniteShift = 2, + SpvLoopControlDependencyLengthShift = 3, + SpvLoopControlMinIterationsShift = 4, + SpvLoopControlMaxIterationsShift = 5, + SpvLoopControlIterationMultipleShift = 6, + SpvLoopControlPeelCountShift = 7, + SpvLoopControlPartialCountShift = 8, + SpvLoopControlMax = 0x7fffffff, +} SpvLoopControlShift; + +typedef enum SpvLoopControlMask_ { + SpvLoopControlMaskNone = 0, + SpvLoopControlUnrollMask = 0x00000001, + SpvLoopControlDontUnrollMask = 0x00000002, + SpvLoopControlDependencyInfiniteMask = 0x00000004, + SpvLoopControlDependencyLengthMask = 0x00000008, + SpvLoopControlMinIterationsMask = 0x00000010, + SpvLoopControlMaxIterationsMask = 0x00000020, + SpvLoopControlIterationMultipleMask = 0x00000040, + SpvLoopControlPeelCountMask = 0x00000080, + SpvLoopControlPartialCountMask = 0x00000100, +} SpvLoopControlMask; + +typedef enum SpvFunctionControlShift_ { + SpvFunctionControlInlineShift = 0, + SpvFunctionControlDontInlineShift = 1, + SpvFunctionControlPureShift = 2, + SpvFunctionControlConstShift = 3, + SpvFunctionControlMax = 0x7fffffff, +} SpvFunctionControlShift; + +typedef enum SpvFunctionControlMask_ { + SpvFunctionControlMaskNone = 0, + SpvFunctionControlInlineMask = 0x00000001, + SpvFunctionControlDontInlineMask = 0x00000002, + SpvFunctionControlPureMask = 0x00000004, + SpvFunctionControlConstMask = 0x00000008, +} SpvFunctionControlMask; + +typedef enum SpvMemorySemanticsShift_ { + SpvMemorySemanticsAcquireShift = 1, + SpvMemorySemanticsReleaseShift = 2, + SpvMemorySemanticsAcquireReleaseShift = 3, + SpvMemorySemanticsSequentiallyConsistentShift = 4, + SpvMemorySemanticsUniformMemoryShift = 6, + SpvMemorySemanticsSubgroupMemoryShift = 7, + SpvMemorySemanticsWorkgroupMemoryShift = 8, + SpvMemorySemanticsCrossWorkgroupMemoryShift = 9, + SpvMemorySemanticsAtomicCounterMemoryShift = 10, + SpvMemorySemanticsImageMemoryShift = 11, + SpvMemorySemanticsOutputMemoryShift = 12, + SpvMemorySemanticsOutputMemoryKHRShift = 12, + SpvMemorySemanticsMakeAvailableShift = 13, + SpvMemorySemanticsMakeAvailableKHRShift = 13, + SpvMemorySemanticsMakeVisibleShift = 14, + SpvMemorySemanticsMakeVisibleKHRShift = 14, + SpvMemorySemanticsVolatileShift = 15, + SpvMemorySemanticsMax = 0x7fffffff, +} SpvMemorySemanticsShift; + +typedef enum SpvMemorySemanticsMask_ { + SpvMemorySemanticsMaskNone = 0, + SpvMemorySemanticsAcquireMask = 0x00000002, + SpvMemorySemanticsReleaseMask = 0x00000004, + SpvMemorySemanticsAcquireReleaseMask = 0x00000008, + SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010, + SpvMemorySemanticsUniformMemoryMask = 0x00000040, + SpvMemorySemanticsSubgroupMemoryMask = 0x00000080, + SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100, + SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, + SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400, + SpvMemorySemanticsImageMemoryMask = 0x00000800, + SpvMemorySemanticsOutputMemoryMask = 0x00001000, + SpvMemorySemanticsOutputMemoryKHRMask = 0x00001000, + SpvMemorySemanticsMakeAvailableMask = 0x00002000, + SpvMemorySemanticsMakeAvailableKHRMask = 0x00002000, + SpvMemorySemanticsMakeVisibleMask = 0x00004000, + SpvMemorySemanticsMakeVisibleKHRMask = 0x00004000, + SpvMemorySemanticsVolatileMask = 0x00008000, +} SpvMemorySemanticsMask; + +typedef enum SpvMemoryAccessShift_ { + SpvMemoryAccessVolatileShift = 0, + SpvMemoryAccessAlignedShift = 1, + SpvMemoryAccessNontemporalShift = 2, + SpvMemoryAccessMakePointerAvailableShift = 3, + SpvMemoryAccessMakePointerAvailableKHRShift = 3, + SpvMemoryAccessMakePointerVisibleShift = 4, + SpvMemoryAccessMakePointerVisibleKHRShift = 4, + SpvMemoryAccessNonPrivatePointerShift = 5, + SpvMemoryAccessNonPrivatePointerKHRShift = 5, + SpvMemoryAccessMax = 0x7fffffff, +} SpvMemoryAccessShift; + +typedef enum SpvMemoryAccessMask_ { + SpvMemoryAccessMaskNone = 0, + SpvMemoryAccessVolatileMask = 0x00000001, + SpvMemoryAccessAlignedMask = 0x00000002, + SpvMemoryAccessNontemporalMask = 0x00000004, + SpvMemoryAccessMakePointerAvailableMask = 0x00000008, + SpvMemoryAccessMakePointerAvailableKHRMask = 0x00000008, + SpvMemoryAccessMakePointerVisibleMask = 0x00000010, + SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010, + SpvMemoryAccessNonPrivatePointerMask = 0x00000020, + SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020, +} SpvMemoryAccessMask; + +typedef enum SpvScope_ { + SpvScopeCrossDevice = 0, + SpvScopeDevice = 1, + SpvScopeWorkgroup = 2, + SpvScopeSubgroup = 3, + SpvScopeInvocation = 4, + SpvScopeQueueFamily = 5, + SpvScopeQueueFamilyKHR = 5, + SpvScopeShaderCallKHR = 6, + SpvScopeMax = 0x7fffffff, +} SpvScope; + +typedef enum SpvGroupOperation_ { + SpvGroupOperationReduce = 0, + SpvGroupOperationInclusiveScan = 1, + SpvGroupOperationExclusiveScan = 2, + SpvGroupOperationClusteredReduce = 3, + SpvGroupOperationPartitionedReduceNV = 6, + SpvGroupOperationPartitionedInclusiveScanNV = 7, + SpvGroupOperationPartitionedExclusiveScanNV = 8, + SpvGroupOperationMax = 0x7fffffff, +} SpvGroupOperation; + +typedef enum SpvKernelEnqueueFlags_ { + SpvKernelEnqueueFlagsNoWait = 0, + SpvKernelEnqueueFlagsWaitKernel = 1, + SpvKernelEnqueueFlagsWaitWorkGroup = 2, + SpvKernelEnqueueFlagsMax = 0x7fffffff, +} SpvKernelEnqueueFlags; + +typedef enum SpvKernelProfilingInfoShift_ { + SpvKernelProfilingInfoCmdExecTimeShift = 0, + SpvKernelProfilingInfoMax = 0x7fffffff, +} SpvKernelProfilingInfoShift; + +typedef enum SpvKernelProfilingInfoMask_ { + SpvKernelProfilingInfoMaskNone = 0, + SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001, +} SpvKernelProfilingInfoMask; + +typedef enum SpvCapability_ { + SpvCapabilityMatrix = 0, + SpvCapabilityShader = 1, + SpvCapabilityGeometry = 2, + SpvCapabilityTessellation = 3, + SpvCapabilityAddresses = 4, + SpvCapabilityLinkage = 5, + SpvCapabilityKernel = 6, + SpvCapabilityVector16 = 7, + SpvCapabilityFloat16Buffer = 8, + SpvCapabilityFloat16 = 9, + SpvCapabilityFloat64 = 10, + SpvCapabilityInt64 = 11, + SpvCapabilityInt64Atomics = 12, + SpvCapabilityImageBasic = 13, + SpvCapabilityImageReadWrite = 14, + SpvCapabilityImageMipmap = 15, + SpvCapabilityPipes = 17, + SpvCapabilityGroups = 18, + SpvCapabilityDeviceEnqueue = 19, + SpvCapabilityLiteralSampler = 20, + SpvCapabilityAtomicStorage = 21, + SpvCapabilityInt16 = 22, + SpvCapabilityTessellationPointSize = 23, + SpvCapabilityGeometryPointSize = 24, + SpvCapabilityImageGatherExtended = 25, + SpvCapabilityStorageImageMultisample = 27, + SpvCapabilityUniformBufferArrayDynamicIndexing = 28, + SpvCapabilitySampledImageArrayDynamicIndexing = 29, + SpvCapabilityStorageBufferArrayDynamicIndexing = 30, + SpvCapabilityStorageImageArrayDynamicIndexing = 31, + SpvCapabilityClipDistance = 32, + SpvCapabilityCullDistance = 33, + SpvCapabilityImageCubeArray = 34, + SpvCapabilitySampleRateShading = 35, + SpvCapabilityImageRect = 36, + SpvCapabilitySampledRect = 37, + SpvCapabilityGenericPointer = 38, + SpvCapabilityInt8 = 39, + SpvCapabilityInputAttachment = 40, + SpvCapabilitySparseResidency = 41, + SpvCapabilityMinLod = 42, + SpvCapabilitySampled1D = 43, + SpvCapabilityImage1D = 44, + SpvCapabilitySampledCubeArray = 45, + SpvCapabilitySampledBuffer = 46, + SpvCapabilityImageBuffer = 47, + SpvCapabilityImageMSArray = 48, + SpvCapabilityStorageImageExtendedFormats = 49, + SpvCapabilityImageQuery = 50, + SpvCapabilityDerivativeControl = 51, + SpvCapabilityInterpolationFunction = 52, + SpvCapabilityTransformFeedback = 53, + SpvCapabilityGeometryStreams = 54, + SpvCapabilityStorageImageReadWithoutFormat = 55, + SpvCapabilityStorageImageWriteWithoutFormat = 56, + SpvCapabilityMultiViewport = 57, + SpvCapabilitySubgroupDispatch = 58, + SpvCapabilityNamedBarrier = 59, + SpvCapabilityPipeStorage = 60, + SpvCapabilityGroupNonUniform = 61, + SpvCapabilityGroupNonUniformVote = 62, + SpvCapabilityGroupNonUniformArithmetic = 63, + SpvCapabilityGroupNonUniformBallot = 64, + SpvCapabilityGroupNonUniformShuffle = 65, + SpvCapabilityGroupNonUniformShuffleRelative = 66, + SpvCapabilityGroupNonUniformClustered = 67, + SpvCapabilityGroupNonUniformQuad = 68, + SpvCapabilityShaderLayer = 69, + SpvCapabilityShaderViewportIndex = 70, + SpvCapabilitySubgroupBallotKHR = 4423, + SpvCapabilityDrawParameters = 4427, + SpvCapabilitySubgroupVoteKHR = 4431, + SpvCapabilityStorageBuffer16BitAccess = 4433, + SpvCapabilityStorageUniformBufferBlock16 = 4433, + SpvCapabilityStorageUniform16 = 4434, + SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434, + SpvCapabilityStoragePushConstant16 = 4435, + SpvCapabilityStorageInputOutput16 = 4436, + SpvCapabilityDeviceGroup = 4437, + SpvCapabilityMultiView = 4439, + SpvCapabilityVariablePointersStorageBuffer = 4441, + SpvCapabilityVariablePointers = 4442, + SpvCapabilityAtomicStorageOps = 4445, + SpvCapabilitySampleMaskPostDepthCoverage = 4447, + SpvCapabilityStorageBuffer8BitAccess = 4448, + SpvCapabilityUniformAndStorageBuffer8BitAccess = 4449, + SpvCapabilityStoragePushConstant8 = 4450, + SpvCapabilityDenormPreserve = 4464, + SpvCapabilityDenormFlushToZero = 4465, + SpvCapabilitySignedZeroInfNanPreserve = 4466, + SpvCapabilityRoundingModeRTE = 4467, + SpvCapabilityRoundingModeRTZ = 4468, + SpvCapabilityRayQueryProvisionalKHR = 4471, + SpvCapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + SpvCapabilityFloat16ImageAMD = 5008, + SpvCapabilityImageGatherBiasLodAMD = 5009, + SpvCapabilityFragmentMaskAMD = 5010, + SpvCapabilityStencilExportEXT = 5013, + SpvCapabilityImageReadWriteLodAMD = 5015, + SpvCapabilityShaderClockKHR = 5055, + SpvCapabilitySampleMaskOverrideCoverageNV = 5249, + SpvCapabilityGeometryShaderPassthroughNV = 5251, + SpvCapabilityShaderViewportIndexLayerEXT = 5254, + SpvCapabilityShaderViewportIndexLayerNV = 5254, + SpvCapabilityShaderViewportMaskNV = 5255, + SpvCapabilityShaderStereoViewNV = 5259, + SpvCapabilityPerViewAttributesNV = 5260, + SpvCapabilityFragmentFullyCoveredEXT = 5265, + SpvCapabilityMeshShadingNV = 5266, + SpvCapabilityImageFootprintNV = 5282, + SpvCapabilityFragmentBarycentricNV = 5284, + SpvCapabilityComputeDerivativeGroupQuadsNV = 5288, + SpvCapabilityFragmentDensityEXT = 5291, + SpvCapabilityShadingRateNV = 5291, + SpvCapabilityGroupNonUniformPartitionedNV = 5297, + SpvCapabilityShaderNonUniform = 5301, + SpvCapabilityShaderNonUniformEXT = 5301, + SpvCapabilityRuntimeDescriptorArray = 5302, + SpvCapabilityRuntimeDescriptorArrayEXT = 5302, + SpvCapabilityInputAttachmentArrayDynamicIndexing = 5303, + SpvCapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + SpvCapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + SpvCapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + SpvCapabilityUniformBufferArrayNonUniformIndexing = 5306, + SpvCapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + SpvCapabilitySampledImageArrayNonUniformIndexing = 5307, + SpvCapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + SpvCapabilityStorageBufferArrayNonUniformIndexing = 5308, + SpvCapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + SpvCapabilityStorageImageArrayNonUniformIndexing = 5309, + SpvCapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + SpvCapabilityInputAttachmentArrayNonUniformIndexing = 5310, + SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + SpvCapabilityRayTracingNV = 5340, + SpvCapabilityVulkanMemoryModel = 5345, + SpvCapabilityVulkanMemoryModelKHR = 5345, + SpvCapabilityVulkanMemoryModelDeviceScope = 5346, + SpvCapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + SpvCapabilityPhysicalStorageBufferAddresses = 5347, + SpvCapabilityPhysicalStorageBufferAddressesEXT = 5347, + SpvCapabilityComputeDerivativeGroupLinearNV = 5350, + SpvCapabilityRayTracingProvisionalKHR = 5353, + SpvCapabilityCooperativeMatrixNV = 5357, + SpvCapabilityFragmentShaderSampleInterlockEXT = 5363, + SpvCapabilityFragmentShaderShadingRateInterlockEXT = 5372, + SpvCapabilityShaderSMBuiltinsNV = 5373, + SpvCapabilityFragmentShaderPixelInterlockEXT = 5378, + SpvCapabilityDemoteToHelperInvocationEXT = 5379, + SpvCapabilitySubgroupShuffleINTEL = 5568, + SpvCapabilitySubgroupBufferBlockIOINTEL = 5569, + SpvCapabilitySubgroupImageBlockIOINTEL = 5570, + SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579, + SpvCapabilityIntegerFunctions2INTEL = 5584, + SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696, + SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + SpvCapabilityMax = 0x7fffffff, +} SpvCapability; + +typedef enum SpvRayFlagsShift_ { + SpvRayFlagsOpaqueKHRShift = 0, + SpvRayFlagsNoOpaqueKHRShift = 1, + SpvRayFlagsTerminateOnFirstHitKHRShift = 2, + SpvRayFlagsSkipClosestHitShaderKHRShift = 3, + SpvRayFlagsCullBackFacingTrianglesKHRShift = 4, + SpvRayFlagsCullFrontFacingTrianglesKHRShift = 5, + SpvRayFlagsCullOpaqueKHRShift = 6, + SpvRayFlagsCullNoOpaqueKHRShift = 7, + SpvRayFlagsSkipTrianglesKHRShift = 8, + SpvRayFlagsSkipAABBsKHRShift = 9, + SpvRayFlagsMax = 0x7fffffff, +} SpvRayFlagsShift; + +typedef enum SpvRayFlagsMask_ { + SpvRayFlagsMaskNone = 0, + SpvRayFlagsOpaqueKHRMask = 0x00000001, + SpvRayFlagsNoOpaqueKHRMask = 0x00000002, + SpvRayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + SpvRayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + SpvRayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + SpvRayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + SpvRayFlagsCullOpaqueKHRMask = 0x00000040, + SpvRayFlagsCullNoOpaqueKHRMask = 0x00000080, + SpvRayFlagsSkipTrianglesKHRMask = 0x00000100, + SpvRayFlagsSkipAABBsKHRMask = 0x00000200, +} SpvRayFlagsMask; + +typedef enum SpvRayQueryIntersection_ { + SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + SpvRayQueryIntersectionMax = 0x7fffffff, +} SpvRayQueryIntersection; + +typedef enum SpvRayQueryCommittedIntersectionType_ { + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + SpvRayQueryCommittedIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCommittedIntersectionType; + +typedef enum SpvRayQueryCandidateIntersectionType_ { + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + SpvRayQueryCandidateIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCandidateIntersectionType; + +typedef enum SpvOp_ { + SpvOpNop = 0, + SpvOpUndef = 1, + SpvOpSourceContinued = 2, + SpvOpSource = 3, + SpvOpSourceExtension = 4, + SpvOpName = 5, + SpvOpMemberName = 6, + SpvOpString = 7, + SpvOpLine = 8, + SpvOpExtension = 10, + SpvOpExtInstImport = 11, + SpvOpExtInst = 12, + SpvOpMemoryModel = 14, + SpvOpEntryPoint = 15, + SpvOpExecutionMode = 16, + SpvOpCapability = 17, + SpvOpTypeVoid = 19, + SpvOpTypeBool = 20, + SpvOpTypeInt = 21, + SpvOpTypeFloat = 22, + SpvOpTypeVector = 23, + SpvOpTypeMatrix = 24, + SpvOpTypeImage = 25, + SpvOpTypeSampler = 26, + SpvOpTypeSampledImage = 27, + SpvOpTypeArray = 28, + SpvOpTypeRuntimeArray = 29, + SpvOpTypeStruct = 30, + SpvOpTypeOpaque = 31, + SpvOpTypePointer = 32, + SpvOpTypeFunction = 33, + SpvOpTypeEvent = 34, + SpvOpTypeDeviceEvent = 35, + SpvOpTypeReserveId = 36, + SpvOpTypeQueue = 37, + SpvOpTypePipe = 38, + SpvOpTypeForwardPointer = 39, + SpvOpConstantTrue = 41, + SpvOpConstantFalse = 42, + SpvOpConstant = 43, + SpvOpConstantComposite = 44, + SpvOpConstantSampler = 45, + SpvOpConstantNull = 46, + SpvOpSpecConstantTrue = 48, + SpvOpSpecConstantFalse = 49, + SpvOpSpecConstant = 50, + SpvOpSpecConstantComposite = 51, + SpvOpSpecConstantOp = 52, + SpvOpFunction = 54, + SpvOpFunctionParameter = 55, + SpvOpFunctionEnd = 56, + SpvOpFunctionCall = 57, + SpvOpVariable = 59, + SpvOpImageTexelPointer = 60, + SpvOpLoad = 61, + SpvOpStore = 62, + SpvOpCopyMemory = 63, + SpvOpCopyMemorySized = 64, + SpvOpAccessChain = 65, + SpvOpInBoundsAccessChain = 66, + SpvOpPtrAccessChain = 67, + SpvOpArrayLength = 68, + SpvOpGenericPtrMemSemantics = 69, + SpvOpInBoundsPtrAccessChain = 70, + SpvOpDecorate = 71, + SpvOpMemberDecorate = 72, + SpvOpDecorationGroup = 73, + SpvOpGroupDecorate = 74, + SpvOpGroupMemberDecorate = 75, + SpvOpVectorExtractDynamic = 77, + SpvOpVectorInsertDynamic = 78, + SpvOpVectorShuffle = 79, + SpvOpCompositeConstruct = 80, + SpvOpCompositeExtract = 81, + SpvOpCompositeInsert = 82, + SpvOpCopyObject = 83, + SpvOpTranspose = 84, + SpvOpSampledImage = 86, + SpvOpImageSampleImplicitLod = 87, + SpvOpImageSampleExplicitLod = 88, + SpvOpImageSampleDrefImplicitLod = 89, + SpvOpImageSampleDrefExplicitLod = 90, + SpvOpImageSampleProjImplicitLod = 91, + SpvOpImageSampleProjExplicitLod = 92, + SpvOpImageSampleProjDrefImplicitLod = 93, + SpvOpImageSampleProjDrefExplicitLod = 94, + SpvOpImageFetch = 95, + SpvOpImageGather = 96, + SpvOpImageDrefGather = 97, + SpvOpImageRead = 98, + SpvOpImageWrite = 99, + SpvOpImage = 100, + SpvOpImageQueryFormat = 101, + SpvOpImageQueryOrder = 102, + SpvOpImageQuerySizeLod = 103, + SpvOpImageQuerySize = 104, + SpvOpImageQueryLod = 105, + SpvOpImageQueryLevels = 106, + SpvOpImageQuerySamples = 107, + SpvOpConvertFToU = 109, + SpvOpConvertFToS = 110, + SpvOpConvertSToF = 111, + SpvOpConvertUToF = 112, + SpvOpUConvert = 113, + SpvOpSConvert = 114, + SpvOpFConvert = 115, + SpvOpQuantizeToF16 = 116, + SpvOpConvertPtrToU = 117, + SpvOpSatConvertSToU = 118, + SpvOpSatConvertUToS = 119, + SpvOpConvertUToPtr = 120, + SpvOpPtrCastToGeneric = 121, + SpvOpGenericCastToPtr = 122, + SpvOpGenericCastToPtrExplicit = 123, + SpvOpBitcast = 124, + SpvOpSNegate = 126, + SpvOpFNegate = 127, + SpvOpIAdd = 128, + SpvOpFAdd = 129, + SpvOpISub = 130, + SpvOpFSub = 131, + SpvOpIMul = 132, + SpvOpFMul = 133, + SpvOpUDiv = 134, + SpvOpSDiv = 135, + SpvOpFDiv = 136, + SpvOpUMod = 137, + SpvOpSRem = 138, + SpvOpSMod = 139, + SpvOpFRem = 140, + SpvOpFMod = 141, + SpvOpVectorTimesScalar = 142, + SpvOpMatrixTimesScalar = 143, + SpvOpVectorTimesMatrix = 144, + SpvOpMatrixTimesVector = 145, + SpvOpMatrixTimesMatrix = 146, + SpvOpOuterProduct = 147, + SpvOpDot = 148, + SpvOpIAddCarry = 149, + SpvOpISubBorrow = 150, + SpvOpUMulExtended = 151, + SpvOpSMulExtended = 152, + SpvOpAny = 154, + SpvOpAll = 155, + SpvOpIsNan = 156, + SpvOpIsInf = 157, + SpvOpIsFinite = 158, + SpvOpIsNormal = 159, + SpvOpSignBitSet = 160, + SpvOpLessOrGreater = 161, + SpvOpOrdered = 162, + SpvOpUnordered = 163, + SpvOpLogicalEqual = 164, + SpvOpLogicalNotEqual = 165, + SpvOpLogicalOr = 166, + SpvOpLogicalAnd = 167, + SpvOpLogicalNot = 168, + SpvOpSelect = 169, + SpvOpIEqual = 170, + SpvOpINotEqual = 171, + SpvOpUGreaterThan = 172, + SpvOpSGreaterThan = 173, + SpvOpUGreaterThanEqual = 174, + SpvOpSGreaterThanEqual = 175, + SpvOpULessThan = 176, + SpvOpSLessThan = 177, + SpvOpULessThanEqual = 178, + SpvOpSLessThanEqual = 179, + SpvOpFOrdEqual = 180, + SpvOpFUnordEqual = 181, + SpvOpFOrdNotEqual = 182, + SpvOpFUnordNotEqual = 183, + SpvOpFOrdLessThan = 184, + SpvOpFUnordLessThan = 185, + SpvOpFOrdGreaterThan = 186, + SpvOpFUnordGreaterThan = 187, + SpvOpFOrdLessThanEqual = 188, + SpvOpFUnordLessThanEqual = 189, + SpvOpFOrdGreaterThanEqual = 190, + SpvOpFUnordGreaterThanEqual = 191, + SpvOpShiftRightLogical = 194, + SpvOpShiftRightArithmetic = 195, + SpvOpShiftLeftLogical = 196, + SpvOpBitwiseOr = 197, + SpvOpBitwiseXor = 198, + SpvOpBitwiseAnd = 199, + SpvOpNot = 200, + SpvOpBitFieldInsert = 201, + SpvOpBitFieldSExtract = 202, + SpvOpBitFieldUExtract = 203, + SpvOpBitReverse = 204, + SpvOpBitCount = 205, + SpvOpDPdx = 207, + SpvOpDPdy = 208, + SpvOpFwidth = 209, + SpvOpDPdxFine = 210, + SpvOpDPdyFine = 211, + SpvOpFwidthFine = 212, + SpvOpDPdxCoarse = 213, + SpvOpDPdyCoarse = 214, + SpvOpFwidthCoarse = 215, + SpvOpEmitVertex = 218, + SpvOpEndPrimitive = 219, + SpvOpEmitStreamVertex = 220, + SpvOpEndStreamPrimitive = 221, + SpvOpControlBarrier = 224, + SpvOpMemoryBarrier = 225, + SpvOpAtomicLoad = 227, + SpvOpAtomicStore = 228, + SpvOpAtomicExchange = 229, + SpvOpAtomicCompareExchange = 230, + SpvOpAtomicCompareExchangeWeak = 231, + SpvOpAtomicIIncrement = 232, + SpvOpAtomicIDecrement = 233, + SpvOpAtomicIAdd = 234, + SpvOpAtomicISub = 235, + SpvOpAtomicSMin = 236, + SpvOpAtomicUMin = 237, + SpvOpAtomicSMax = 238, + SpvOpAtomicUMax = 239, + SpvOpAtomicAnd = 240, + SpvOpAtomicOr = 241, + SpvOpAtomicXor = 242, + SpvOpPhi = 245, + SpvOpLoopMerge = 246, + SpvOpSelectionMerge = 247, + SpvOpLabel = 248, + SpvOpBranch = 249, + SpvOpBranchConditional = 250, + SpvOpSwitch = 251, + SpvOpKill = 252, + SpvOpReturn = 253, + SpvOpReturnValue = 254, + SpvOpUnreachable = 255, + SpvOpLifetimeStart = 256, + SpvOpLifetimeStop = 257, + SpvOpGroupAsyncCopy = 259, + SpvOpGroupWaitEvents = 260, + SpvOpGroupAll = 261, + SpvOpGroupAny = 262, + SpvOpGroupBroadcast = 263, + SpvOpGroupIAdd = 264, + SpvOpGroupFAdd = 265, + SpvOpGroupFMin = 266, + SpvOpGroupUMin = 267, + SpvOpGroupSMin = 268, + SpvOpGroupFMax = 269, + SpvOpGroupUMax = 270, + SpvOpGroupSMax = 271, + SpvOpReadPipe = 274, + SpvOpWritePipe = 275, + SpvOpReservedReadPipe = 276, + SpvOpReservedWritePipe = 277, + SpvOpReserveReadPipePackets = 278, + SpvOpReserveWritePipePackets = 279, + SpvOpCommitReadPipe = 280, + SpvOpCommitWritePipe = 281, + SpvOpIsValidReserveId = 282, + SpvOpGetNumPipePackets = 283, + SpvOpGetMaxPipePackets = 284, + SpvOpGroupReserveReadPipePackets = 285, + SpvOpGroupReserveWritePipePackets = 286, + SpvOpGroupCommitReadPipe = 287, + SpvOpGroupCommitWritePipe = 288, + SpvOpEnqueueMarker = 291, + SpvOpEnqueueKernel = 292, + SpvOpGetKernelNDrangeSubGroupCount = 293, + SpvOpGetKernelNDrangeMaxSubGroupSize = 294, + SpvOpGetKernelWorkGroupSize = 295, + SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296, + SpvOpRetainEvent = 297, + SpvOpReleaseEvent = 298, + SpvOpCreateUserEvent = 299, + SpvOpIsValidEvent = 300, + SpvOpSetUserEventStatus = 301, + SpvOpCaptureEventProfilingInfo = 302, + SpvOpGetDefaultQueue = 303, + SpvOpBuildNDRange = 304, + SpvOpImageSparseSampleImplicitLod = 305, + SpvOpImageSparseSampleExplicitLod = 306, + SpvOpImageSparseSampleDrefImplicitLod = 307, + SpvOpImageSparseSampleDrefExplicitLod = 308, + SpvOpImageSparseSampleProjImplicitLod = 309, + SpvOpImageSparseSampleProjExplicitLod = 310, + SpvOpImageSparseSampleProjDrefImplicitLod = 311, + SpvOpImageSparseSampleProjDrefExplicitLod = 312, + SpvOpImageSparseFetch = 313, + SpvOpImageSparseGather = 314, + SpvOpImageSparseDrefGather = 315, + SpvOpImageSparseTexelsResident = 316, + SpvOpNoLine = 317, + SpvOpAtomicFlagTestAndSet = 318, + SpvOpAtomicFlagClear = 319, + SpvOpImageSparseRead = 320, + SpvOpSizeOf = 321, + SpvOpTypePipeStorage = 322, + SpvOpConstantPipeStorage = 323, + SpvOpCreatePipeFromPipeStorage = 324, + SpvOpGetKernelLocalSizeForSubgroupCount = 325, + SpvOpGetKernelMaxNumSubgroups = 326, + SpvOpTypeNamedBarrier = 327, + SpvOpNamedBarrierInitialize = 328, + SpvOpMemoryNamedBarrier = 329, + SpvOpModuleProcessed = 330, + SpvOpExecutionModeId = 331, + SpvOpDecorateId = 332, + SpvOpGroupNonUniformElect = 333, + SpvOpGroupNonUniformAll = 334, + SpvOpGroupNonUniformAny = 335, + SpvOpGroupNonUniformAllEqual = 336, + SpvOpGroupNonUniformBroadcast = 337, + SpvOpGroupNonUniformBroadcastFirst = 338, + SpvOpGroupNonUniformBallot = 339, + SpvOpGroupNonUniformInverseBallot = 340, + SpvOpGroupNonUniformBallotBitExtract = 341, + SpvOpGroupNonUniformBallotBitCount = 342, + SpvOpGroupNonUniformBallotFindLSB = 343, + SpvOpGroupNonUniformBallotFindMSB = 344, + SpvOpGroupNonUniformShuffle = 345, + SpvOpGroupNonUniformShuffleXor = 346, + SpvOpGroupNonUniformShuffleUp = 347, + SpvOpGroupNonUniformShuffleDown = 348, + SpvOpGroupNonUniformIAdd = 349, + SpvOpGroupNonUniformFAdd = 350, + SpvOpGroupNonUniformIMul = 351, + SpvOpGroupNonUniformFMul = 352, + SpvOpGroupNonUniformSMin = 353, + SpvOpGroupNonUniformUMin = 354, + SpvOpGroupNonUniformFMin = 355, + SpvOpGroupNonUniformSMax = 356, + SpvOpGroupNonUniformUMax = 357, + SpvOpGroupNonUniformFMax = 358, + SpvOpGroupNonUniformBitwiseAnd = 359, + SpvOpGroupNonUniformBitwiseOr = 360, + SpvOpGroupNonUniformBitwiseXor = 361, + SpvOpGroupNonUniformLogicalAnd = 362, + SpvOpGroupNonUniformLogicalOr = 363, + SpvOpGroupNonUniformLogicalXor = 364, + SpvOpGroupNonUniformQuadBroadcast = 365, + SpvOpGroupNonUniformQuadSwap = 366, + SpvOpCopyLogical = 400, + SpvOpPtrEqual = 401, + SpvOpPtrNotEqual = 402, + SpvOpPtrDiff = 403, + SpvOpSubgroupBallotKHR = 4421, + SpvOpSubgroupFirstInvocationKHR = 4422, + SpvOpSubgroupAllKHR = 4428, + SpvOpSubgroupAnyKHR = 4429, + SpvOpSubgroupAllEqualKHR = 4430, + SpvOpSubgroupReadInvocationKHR = 4432, + SpvOpTypeRayQueryProvisionalKHR = 4472, + SpvOpRayQueryInitializeKHR = 4473, + SpvOpRayQueryTerminateKHR = 4474, + SpvOpRayQueryGenerateIntersectionKHR = 4475, + SpvOpRayQueryConfirmIntersectionKHR = 4476, + SpvOpRayQueryProceedKHR = 4477, + SpvOpRayQueryGetIntersectionTypeKHR = 4479, + SpvOpGroupIAddNonUniformAMD = 5000, + SpvOpGroupFAddNonUniformAMD = 5001, + SpvOpGroupFMinNonUniformAMD = 5002, + SpvOpGroupUMinNonUniformAMD = 5003, + SpvOpGroupSMinNonUniformAMD = 5004, + SpvOpGroupFMaxNonUniformAMD = 5005, + SpvOpGroupUMaxNonUniformAMD = 5006, + SpvOpGroupSMaxNonUniformAMD = 5007, + SpvOpFragmentMaskFetchAMD = 5011, + SpvOpFragmentFetchAMD = 5012, + SpvOpReadClockKHR = 5056, + SpvOpImageSampleFootprintNV = 5283, + SpvOpGroupNonUniformPartitionNV = 5296, + SpvOpWritePackedPrimitiveIndices4x8NV = 5299, + SpvOpReportIntersectionKHR = 5334, + SpvOpReportIntersectionNV = 5334, + SpvOpIgnoreIntersectionKHR = 5335, + SpvOpIgnoreIntersectionNV = 5335, + SpvOpTerminateRayKHR = 5336, + SpvOpTerminateRayNV = 5336, + SpvOpTraceNV = 5337, + SpvOpTraceRayKHR = 5337, + SpvOpTypeAccelerationStructureKHR = 5341, + SpvOpTypeAccelerationStructureNV = 5341, + SpvOpExecuteCallableKHR = 5344, + SpvOpExecuteCallableNV = 5344, + SpvOpTypeCooperativeMatrixNV = 5358, + SpvOpCooperativeMatrixLoadNV = 5359, + SpvOpCooperativeMatrixStoreNV = 5360, + SpvOpCooperativeMatrixMulAddNV = 5361, + SpvOpCooperativeMatrixLengthNV = 5362, + SpvOpBeginInvocationInterlockEXT = 5364, + SpvOpEndInvocationInterlockEXT = 5365, + SpvOpDemoteToHelperInvocationEXT = 5380, + SpvOpIsHelperInvocationEXT = 5381, + SpvOpSubgroupShuffleINTEL = 5571, + SpvOpSubgroupShuffleDownINTEL = 5572, + SpvOpSubgroupShuffleUpINTEL = 5573, + SpvOpSubgroupShuffleXorINTEL = 5574, + SpvOpSubgroupBlockReadINTEL = 5575, + SpvOpSubgroupBlockWriteINTEL = 5576, + SpvOpSubgroupImageBlockReadINTEL = 5577, + SpvOpSubgroupImageBlockWriteINTEL = 5578, + SpvOpSubgroupImageMediaBlockReadINTEL = 5580, + SpvOpSubgroupImageMediaBlockWriteINTEL = 5581, + SpvOpUCountLeadingZerosINTEL = 5585, + SpvOpUCountTrailingZerosINTEL = 5586, + SpvOpAbsISubINTEL = 5587, + SpvOpAbsUSubINTEL = 5588, + SpvOpIAddSatINTEL = 5589, + SpvOpUAddSatINTEL = 5590, + SpvOpIAverageINTEL = 5591, + SpvOpUAverageINTEL = 5592, + SpvOpIAverageRoundedINTEL = 5593, + SpvOpUAverageRoundedINTEL = 5594, + SpvOpISubSatINTEL = 5595, + SpvOpUSubSatINTEL = 5596, + SpvOpIMul32x16INTEL = 5597, + SpvOpUMul32x16INTEL = 5598, + SpvOpDecorateString = 5632, + SpvOpDecorateStringGOOGLE = 5632, + SpvOpMemberDecorateString = 5633, + SpvOpMemberDecorateStringGOOGLE = 5633, + SpvOpVmeImageINTEL = 5699, + SpvOpTypeVmeImageINTEL = 5700, + SpvOpTypeAvcImePayloadINTEL = 5701, + SpvOpTypeAvcRefPayloadINTEL = 5702, + SpvOpTypeAvcSicPayloadINTEL = 5703, + SpvOpTypeAvcMcePayloadINTEL = 5704, + SpvOpTypeAvcMceResultINTEL = 5705, + SpvOpTypeAvcImeResultINTEL = 5706, + SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + SpvOpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + SpvOpTypeAvcImeDualReferenceStreaminINTEL = 5710, + SpvOpTypeAvcRefResultINTEL = 5711, + SpvOpTypeAvcSicResultINTEL = 5712, + SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + SpvOpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + SpvOpSubgroupAvcMceConvertToImeResultINTEL = 5733, + SpvOpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + SpvOpSubgroupAvcMceConvertToRefResultINTEL = 5735, + SpvOpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + SpvOpSubgroupAvcMceConvertToSicResultINTEL = 5737, + SpvOpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + SpvOpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + SpvOpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + SpvOpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + SpvOpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + SpvOpSubgroupAvcImeInitializeINTEL = 5747, + SpvOpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + SpvOpSubgroupAvcImeSetDualReferenceINTEL = 5749, + SpvOpSubgroupAvcImeRefWindowSizeINTEL = 5750, + SpvOpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + SpvOpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + SpvOpSubgroupAvcImeSetWeightedSadINTEL = 5756, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + SpvOpSubgroupAvcImeConvertToMceResultINTEL = 5765, + SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + SpvOpSubgroupAvcImeGetBorderReachedINTEL = 5776, + SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + SpvOpSubgroupAvcFmeInitializeINTEL = 5781, + SpvOpSubgroupAvcBmeInitializeINTEL = 5782, + SpvOpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + SpvOpSubgroupAvcRefConvertToMceResultINTEL = 5790, + SpvOpSubgroupAvcSicInitializeINTEL = 5791, + SpvOpSubgroupAvcSicConfigureSkcINTEL = 5792, + SpvOpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + SpvOpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + SpvOpSubgroupAvcSicEvaluateIpeINTEL = 5803, + SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + SpvOpSubgroupAvcSicConvertToMceResultINTEL = 5808, + SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + SpvOpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + SpvOpRayQueryGetRayTMinKHR = 6016, + SpvOpRayQueryGetRayFlagsKHR = 6017, + SpvOpRayQueryGetIntersectionTKHR = 6018, + SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + SpvOpRayQueryGetIntersectionInstanceIdKHR = 6020, + SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + SpvOpRayQueryGetIntersectionGeometryIndexKHR = 6022, + SpvOpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + SpvOpRayQueryGetIntersectionBarycentricsKHR = 6024, + SpvOpRayQueryGetIntersectionFrontFaceKHR = 6025, + SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + SpvOpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + SpvOpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + SpvOpRayQueryGetWorldRayDirectionKHR = 6029, + SpvOpRayQueryGetWorldRayOriginKHR = 6030, + SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031, + SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032, + SpvOpMax = 0x7fffffff, +} SpvOp; + +#ifdef SPV_ENABLE_UTILITY_CODE +inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case SpvOpNop: *hasResult = false; *hasResultType = false; break; + case SpvOpUndef: *hasResult = true; *hasResultType = true; break; + case SpvOpSourceContinued: *hasResult = false; *hasResultType = false; break; + case SpvOpSource: *hasResult = false; *hasResultType = false; break; + case SpvOpSourceExtension: *hasResult = false; *hasResultType = false; break; + case SpvOpName: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberName: *hasResult = false; *hasResultType = false; break; + case SpvOpString: *hasResult = true; *hasResultType = false; break; + case SpvOpLine: *hasResult = false; *hasResultType = false; break; + case SpvOpExtension: *hasResult = false; *hasResultType = false; break; + case SpvOpExtInstImport: *hasResult = true; *hasResultType = false; break; + case SpvOpExtInst: *hasResult = true; *hasResultType = true; break; + case SpvOpMemoryModel: *hasResult = false; *hasResultType = false; break; + case SpvOpEntryPoint: *hasResult = false; *hasResultType = false; break; + case SpvOpExecutionMode: *hasResult = false; *hasResultType = false; break; + case SpvOpCapability: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeVoid: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeBool: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeInt: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeFloat: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeVector: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeImage: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeSampler: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeArray: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeStruct: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case SpvOpTypePointer: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeFunction: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeEvent: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeQueue: *hasResult = true; *hasResultType = false; break; + case SpvOpTypePipe: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case SpvOpConstantTrue: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantFalse: *hasResult = true; *hasResultType = true; break; + case SpvOpConstant: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantComposite: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantSampler: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantNull: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstant: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case SpvOpFunction: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case SpvOpFunctionCall: *hasResult = true; *hasResultType = true; break; + case SpvOpVariable: *hasResult = true; *hasResultType = true; break; + case SpvOpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case SpvOpLoad: *hasResult = true; *hasResultType = true; break; + case SpvOpStore: *hasResult = false; *hasResultType = false; break; + case SpvOpCopyMemory: *hasResult = false; *hasResultType = false; break; + case SpvOpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case SpvOpAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpArrayLength: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case SpvOpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case SpvOpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case SpvOpCopyObject: *hasResult = true; *hasResultType = true; break; + case SpvOpTranspose: *hasResult = true; *hasResultType = true; break; + case SpvOpSampledImage: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageFetch: *hasResult = true; *hasResultType = true; break; + case SpvOpImageGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageRead: *hasResult = true; *hasResultType = true; break; + case SpvOpImageWrite: *hasResult = false; *hasResultType = false; break; + case SpvOpImage: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertFToU: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertFToS: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertSToF: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertUToF: *hasResult = true; *hasResultType = true; break; + case SpvOpUConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpSConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpFConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case SpvOpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case SpvOpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case SpvOpBitcast: *hasResult = true; *hasResultType = true; break; + case SpvOpSNegate: *hasResult = true; *hasResultType = true; break; + case SpvOpFNegate: *hasResult = true; *hasResultType = true; break; + case SpvOpIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpISub: *hasResult = true; *hasResultType = true; break; + case SpvOpFSub: *hasResult = true; *hasResultType = true; break; + case SpvOpIMul: *hasResult = true; *hasResultType = true; break; + case SpvOpFMul: *hasResult = true; *hasResultType = true; break; + case SpvOpUDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpSDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpFDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpUMod: *hasResult = true; *hasResultType = true; break; + case SpvOpSRem: *hasResult = true; *hasResultType = true; break; + case SpvOpSMod: *hasResult = true; *hasResultType = true; break; + case SpvOpFRem: *hasResult = true; *hasResultType = true; break; + case SpvOpFMod: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case SpvOpOuterProduct: *hasResult = true; *hasResultType = true; break; + case SpvOpDot: *hasResult = true; *hasResultType = true; break; + case SpvOpIAddCarry: *hasResult = true; *hasResultType = true; break; + case SpvOpISubBorrow: *hasResult = true; *hasResultType = true; break; + case SpvOpUMulExtended: *hasResult = true; *hasResultType = true; break; + case SpvOpSMulExtended: *hasResult = true; *hasResultType = true; break; + case SpvOpAny: *hasResult = true; *hasResultType = true; break; + case SpvOpAll: *hasResult = true; *hasResultType = true; break; + case SpvOpIsNan: *hasResult = true; *hasResultType = true; break; + case SpvOpIsInf: *hasResult = true; *hasResultType = true; break; + case SpvOpIsFinite: *hasResult = true; *hasResultType = true; break; + case SpvOpIsNormal: *hasResult = true; *hasResultType = true; break; + case SpvOpSignBitSet: *hasResult = true; *hasResultType = true; break; + case SpvOpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case SpvOpOrdered: *hasResult = true; *hasResultType = true; break; + case SpvOpUnordered: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalOr: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalNot: *hasResult = true; *hasResultType = true; break; + case SpvOpSelect: *hasResult = true; *hasResultType = true; break; + case SpvOpIEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpINotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpULessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpSLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpNot: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpBitReverse: *hasResult = true; *hasResultType = true; break; + case SpvOpBitCount: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdx: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdy: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidth: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdxFine: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdyFine: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidthFine: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpEmitVertex: *hasResult = false; *hasResultType = false; break; + case SpvOpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case SpvOpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case SpvOpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case SpvOpControlBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicStore: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicISub: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicOr: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicXor: *hasResult = true; *hasResultType = true; break; + case SpvOpPhi: *hasResult = true; *hasResultType = true; break; + case SpvOpLoopMerge: *hasResult = false; *hasResultType = false; break; + case SpvOpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case SpvOpLabel: *hasResult = true; *hasResultType = false; break; + case SpvOpBranch: *hasResult = false; *hasResultType = false; break; + case SpvOpBranchConditional: *hasResult = false; *hasResultType = false; break; + case SpvOpSwitch: *hasResult = false; *hasResultType = false; break; + case SpvOpKill: *hasResult = false; *hasResultType = false; break; + case SpvOpReturn: *hasResult = false; *hasResultType = false; break; + case SpvOpReturnValue: *hasResult = false; *hasResultType = false; break; + case SpvOpUnreachable: *hasResult = false; *hasResultType = false; break; + case SpvOpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case SpvOpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupAll: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupAny: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpReadPipe: *hasResult = true; *hasResultType = true; break; + case SpvOpWritePipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case SpvOpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case SpvOpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case SpvOpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case SpvOpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case SpvOpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case SpvOpRetainEvent: *hasResult = false; *hasResultType = false; break; + case SpvOpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case SpvOpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case SpvOpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case SpvOpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case SpvOpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case SpvOpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case SpvOpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case SpvOpNoLine: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case SpvOpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case SpvOpSizeOf: *hasResult = true; *hasResultType = true; break; + case SpvOpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case SpvOpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case SpvOpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case SpvOpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case SpvOpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case SpvOpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case SpvOpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case SpvOpDecorateId: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case SpvOpCopyLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrDiff: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case SpvOpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case SpvOpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case SpvOpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTraceNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break; + case SpvOpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case SpvOpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case SpvOpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case SpvOpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case SpvOpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case SpvOpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpDecorateString: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case SpvOpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +#endif + diff --git a/ios/include/spirv_cross/spirv.hpp b/ios/include/spirv_cross/spirv.hpp new file mode 100644 index 00000000..9f98683d --- /dev/null +++ b/ios/include/spirv_cross/spirv.hpp @@ -0,0 +1,2114 @@ +// Copyright (c) 2014-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. + +// 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 +// +// - 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 +// +// 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 0x10500 +#define SPV_REVISION 1 + +static const unsigned int MagicNumber = 0x07230203; +static const unsigned int Version = 0x00010500; +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, + 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, + 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, + ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, + ExecutionModeStencilRefReplacingEXT = 5027, + ExecutionModeOutputLinesNV = 5269, + ExecutionModeOutputPrimitivesNV = 5270, + ExecutionModeDerivativeGroupQuadsNV = 5289, + ExecutionModeDerivativeGroupLinearNV = 5290, + ExecutionModeOutputTrianglesNV = 5298, + ExecutionModePixelInterlockOrderedEXT = 5366, + ExecutionModePixelInterlockUnorderedEXT = 5367, + ExecutionModeSampleInterlockOrderedEXT = 5368, + ExecutionModeSampleInterlockUnorderedEXT = 5369, + ExecutionModeShadingRateInterlockOrderedEXT = 5370, + ExecutionModeShadingRateInterlockUnorderedEXT = 5371, + 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, + 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, + StorageClassMax = 0x7fffffff, +}; + +enum Dim { + Dim1D = 0, + Dim2D = 1, + Dim3D = 2, + DimCube = 3, + DimRect = 4, + DimBuffer = 5, + DimSubpassData = 6, + 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, + 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, + 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, + ImageOperandsMax = 0x7fffffff, +}; + +enum ImageOperandsMask { + 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, +}; + +enum FPFastMathModeShift { + FPFastMathModeNotNaNShift = 0, + FPFastMathModeNotInfShift = 1, + FPFastMathModeNSZShift = 2, + FPFastMathModeAllowRecipShift = 3, + FPFastMathModeFastShift = 4, + FPFastMathModeMax = 0x7fffffff, +}; + +enum FPFastMathModeMask { + FPFastMathModeMaskNone = 0, + FPFastMathModeNotNaNMask = 0x00000001, + FPFastMathModeNotInfMask = 0x00000002, + FPFastMathModeNSZMask = 0x00000004, + FPFastMathModeAllowRecipMask = 0x00000008, + FPFastMathModeFastMask = 0x00000010, +}; + +enum FPRoundingMode { + FPRoundingModeRTE = 0, + FPRoundingModeRTZ = 1, + FPRoundingModeRTP = 2, + FPRoundingModeRTN = 3, + FPRoundingModeMax = 0x7fffffff, +}; + +enum LinkageType { + LinkageTypeExport = 0, + LinkageTypeImport = 1, + 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, + 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, + DecorationExplicitInterpAMD = 4999, + DecorationOverrideCoverageNV = 5248, + DecorationPassthroughNV = 5250, + DecorationViewportRelativeNV = 5252, + DecorationSecondaryViewportRelativeNV = 5256, + DecorationPerPrimitiveNV = 5271, + DecorationPerViewNV = 5272, + DecorationPerTaskNV = 5273, + DecorationPerVertexNV = 5285, + DecorationNonUniform = 5300, + DecorationNonUniformEXT = 5300, + DecorationRestrictPointer = 5355, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointer = 5356, + DecorationAliasedPointerEXT = 5356, + DecorationCounterBuffer = 5634, + DecorationHlslCounterBufferGOOGLE = 5634, + DecorationHlslSemanticGOOGLE = 5635, + DecorationUserSemantic = 5635, + DecorationUserTypeGOOGLE = 5636, + 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, + 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, + BuiltInDeviceIndex = 4438, + BuiltInViewIndex = 4440, + BuiltInBaryCoordNoPerspAMD = 4992, + BuiltInBaryCoordNoPerspCentroidAMD = 4993, + BuiltInBaryCoordNoPerspSampleAMD = 4994, + BuiltInBaryCoordSmoothAMD = 4995, + BuiltInBaryCoordSmoothCentroidAMD = 4996, + BuiltInBaryCoordSmoothSampleAMD = 4997, + BuiltInBaryCoordPullModelAMD = 4998, + BuiltInFragStencilRefEXT = 5014, + 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, + BuiltInBaryCoordNV = 5286, + BuiltInBaryCoordNoPerspNV = 5287, + BuiltInFragSizeEXT = 5292, + BuiltInFragmentSizeNV = 5292, + BuiltInFragInvocationCountEXT = 5293, + BuiltInInvocationsPerPixelNV = 5293, + 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, + BuiltInHitTKHR = 5332, + BuiltInHitTNV = 5332, + BuiltInHitKindKHR = 5333, + BuiltInHitKindNV = 5333, + BuiltInIncomingRayFlagsKHR = 5351, + BuiltInIncomingRayFlagsNV = 5351, + BuiltInRayGeometryIndexKHR = 5352, + BuiltInWarpsPerSMNV = 5374, + BuiltInSMCountNV = 5375, + BuiltInWarpIDNV = 5376, + BuiltInSMIDNV = 5377, + BuiltInMax = 0x7fffffff, +}; + +enum SelectionControlShift { + SelectionControlFlattenShift = 0, + SelectionControlDontFlattenShift = 1, + SelectionControlMax = 0x7fffffff, +}; + +enum SelectionControlMask { + 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, + LoopControlMax = 0x7fffffff, +}; + +enum LoopControlMask { + LoopControlMaskNone = 0, + LoopControlUnrollMask = 0x00000001, + LoopControlDontUnrollMask = 0x00000002, + LoopControlDependencyInfiniteMask = 0x00000004, + LoopControlDependencyLengthMask = 0x00000008, + LoopControlMinIterationsMask = 0x00000010, + LoopControlMaxIterationsMask = 0x00000020, + LoopControlIterationMultipleMask = 0x00000040, + LoopControlPeelCountMask = 0x00000080, + LoopControlPartialCountMask = 0x00000100, +}; + +enum FunctionControlShift { + FunctionControlInlineShift = 0, + FunctionControlDontInlineShift = 1, + FunctionControlPureShift = 2, + FunctionControlConstShift = 3, + FunctionControlMax = 0x7fffffff, +}; + +enum FunctionControlMask { + FunctionControlMaskNone = 0, + FunctionControlInlineMask = 0x00000001, + FunctionControlDontInlineMask = 0x00000002, + FunctionControlPureMask = 0x00000004, + FunctionControlConstMask = 0x00000008, +}; + +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 { + 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, + MemoryAccessMax = 0x7fffffff, +}; + +enum MemoryAccessMask { + MemoryAccessMaskNone = 0, + MemoryAccessVolatileMask = 0x00000001, + MemoryAccessAlignedMask = 0x00000002, + MemoryAccessNontemporalMask = 0x00000004, + MemoryAccessMakePointerAvailableMask = 0x00000008, + MemoryAccessMakePointerAvailableKHRMask = 0x00000008, + MemoryAccessMakePointerVisibleMask = 0x00000010, + MemoryAccessMakePointerVisibleKHRMask = 0x00000010, + MemoryAccessNonPrivatePointerMask = 0x00000020, + MemoryAccessNonPrivatePointerKHRMask = 0x00000020, +}; + +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 { + 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, + CapabilitySubgroupBallotKHR = 4423, + CapabilityDrawParameters = 4427, + 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, + CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478, + CapabilityFloat16ImageAMD = 5008, + CapabilityImageGatherBiasLodAMD = 5009, + CapabilityFragmentMaskAMD = 5010, + CapabilityStencilExportEXT = 5013, + CapabilityImageReadWriteLodAMD = 5015, + CapabilityShaderClockKHR = 5055, + CapabilitySampleMaskOverrideCoverageNV = 5249, + CapabilityGeometryShaderPassthroughNV = 5251, + CapabilityShaderViewportIndexLayerEXT = 5254, + CapabilityShaderViewportIndexLayerNV = 5254, + CapabilityShaderViewportMaskNV = 5255, + CapabilityShaderStereoViewNV = 5259, + CapabilityPerViewAttributesNV = 5260, + CapabilityFragmentFullyCoveredEXT = 5265, + CapabilityMeshShadingNV = 5266, + CapabilityImageFootprintNV = 5282, + CapabilityFragmentBarycentricNV = 5284, + 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, + CapabilityRayTracingNV = 5340, + CapabilityVulkanMemoryModel = 5345, + CapabilityVulkanMemoryModelKHR = 5345, + CapabilityVulkanMemoryModelDeviceScope = 5346, + CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddresses = 5347, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, + CapabilityComputeDerivativeGroupLinearNV = 5350, + CapabilityRayTracingProvisionalKHR = 5353, + CapabilityCooperativeMatrixNV = 5357, + CapabilityFragmentShaderSampleInterlockEXT = 5363, + CapabilityFragmentShaderShadingRateInterlockEXT = 5372, + CapabilityShaderSMBuiltinsNV = 5373, + CapabilityFragmentShaderPixelInterlockEXT = 5378, + CapabilityDemoteToHelperInvocationEXT = 5379, + CapabilitySubgroupShuffleINTEL = 5568, + CapabilitySubgroupBufferBlockIOINTEL = 5569, + CapabilitySubgroupImageBlockIOINTEL = 5570, + CapabilitySubgroupImageMediaBlockIOINTEL = 5579, + CapabilityIntegerFunctions2INTEL = 5584, + CapabilitySubgroupAvcMotionEstimationINTEL = 5696, + CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + CapabilityMax = 0x7fffffff, +}; + +enum RayFlagsShift { + RayFlagsOpaqueKHRShift = 0, + RayFlagsNoOpaqueKHRShift = 1, + RayFlagsTerminateOnFirstHitKHRShift = 2, + RayFlagsSkipClosestHitShaderKHRShift = 3, + RayFlagsCullBackFacingTrianglesKHRShift = 4, + RayFlagsCullFrontFacingTrianglesKHRShift = 5, + RayFlagsCullOpaqueKHRShift = 6, + RayFlagsCullNoOpaqueKHRShift = 7, + RayFlagsSkipTrianglesKHRShift = 8, + RayFlagsSkipAABBsKHRShift = 9, + RayFlagsMax = 0x7fffffff, +}; + +enum RayFlagsMask { + RayFlagsMaskNone = 0, + RayFlagsOpaqueKHRMask = 0x00000001, + RayFlagsNoOpaqueKHRMask = 0x00000002, + RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + RayFlagsCullOpaqueKHRMask = 0x00000040, + RayFlagsCullNoOpaqueKHRMask = 0x00000080, + RayFlagsSkipTrianglesKHRMask = 0x00000100, + RayFlagsSkipAABBsKHRMask = 0x00000200, +}; + +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 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, + OpSubgroupBallotKHR = 4421, + OpSubgroupFirstInvocationKHR = 4422, + OpSubgroupAllKHR = 4428, + OpSubgroupAnyKHR = 4429, + OpSubgroupAllEqualKHR = 4430, + OpSubgroupReadInvocationKHR = 4432, + OpTypeRayQueryProvisionalKHR = 4472, + OpRayQueryInitializeKHR = 4473, + OpRayQueryTerminateKHR = 4474, + OpRayQueryGenerateIntersectionKHR = 4475, + OpRayQueryConfirmIntersectionKHR = 4476, + OpRayQueryProceedKHR = 4477, + OpRayQueryGetIntersectionTypeKHR = 4479, + OpGroupIAddNonUniformAMD = 5000, + OpGroupFAddNonUniformAMD = 5001, + OpGroupFMinNonUniformAMD = 5002, + OpGroupUMinNonUniformAMD = 5003, + OpGroupSMinNonUniformAMD = 5004, + OpGroupFMaxNonUniformAMD = 5005, + OpGroupUMaxNonUniformAMD = 5006, + OpGroupSMaxNonUniformAMD = 5007, + OpFragmentMaskFetchAMD = 5011, + OpFragmentFetchAMD = 5012, + OpReadClockKHR = 5056, + OpImageSampleFootprintNV = 5283, + OpGroupNonUniformPartitionNV = 5296, + OpWritePackedPrimitiveIndices4x8NV = 5299, + OpReportIntersectionKHR = 5334, + OpReportIntersectionNV = 5334, + OpIgnoreIntersectionKHR = 5335, + OpIgnoreIntersectionNV = 5335, + OpTerminateRayKHR = 5336, + OpTerminateRayNV = 5336, + OpTraceNV = 5337, + OpTraceRayKHR = 5337, + OpTypeAccelerationStructureKHR = 5341, + OpTypeAccelerationStructureNV = 5341, + OpExecuteCallableKHR = 5344, + OpExecuteCallableNV = 5344, + OpTypeCooperativeMatrixNV = 5358, + OpCooperativeMatrixLoadNV = 5359, + OpCooperativeMatrixStoreNV = 5360, + OpCooperativeMatrixMulAddNV = 5361, + OpCooperativeMatrixLengthNV = 5362, + OpBeginInvocationInterlockEXT = 5364, + OpEndInvocationInterlockEXT = 5365, + OpDemoteToHelperInvocationEXT = 5380, + OpIsHelperInvocationEXT = 5381, + 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, + 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, + 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, + OpMax = 0x7fffffff, +}; + +#ifdef SPV_ENABLE_UTILITY_CODE +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 OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case OpSubgroupReadInvocationKHR: *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 OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case OpReportIntersectionNV: *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 OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case OpTypeRayQueryProvisionalKHR: *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 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 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 OpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case OpIsHelperInvocationEXT: *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 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; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +// Overload operator| for mask bit combining + +inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } +inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } +inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } +inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } +inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } +inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } +inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } +inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } +inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } + +} // end namespace spv + +#endif // #ifndef spirv_HPP + diff --git a/ios/include/spirv_cross/spirv_cfg.hpp b/ios/include/spirv_cross/spirv_cfg.hpp new file mode 100644 index 00000000..9f3e62a1 --- /dev/null +++ b/ios/include/spirv_cross/spirv_cfg.hpp @@ -0,0 +1,156 @@ +/* + * Copyright 2016-2020 Arm Limited + * + * 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 SPIRV_CROSS_CFG_HPP +#define SPIRV_CROSS_CFG_HPP + +#include "spirv_common.hpp" +#include + +namespace SPIRV_CROSS_NAMESPACE +{ +class Compiler; +class CFG +{ +public: + CFG(Compiler &compiler, const SPIRFunction &function); + + Compiler &get_compiler() + { + return compiler; + } + + const Compiler &get_compiler() const + { + return compiler; + } + + const SPIRFunction &get_function() const + { + return func; + } + + uint32_t get_immediate_dominator(uint32_t block) const + { + auto itr = immediate_dominators.find(block); + if (itr != std::end(immediate_dominators)) + return itr->second; + else + return 0; + } + + uint32_t get_visit_order(uint32_t block) const + { + auto itr = visit_order.find(block); + assert(itr != std::end(visit_order)); + int v = itr->second.get(); + assert(v > 0); + return uint32_t(v); + } + + uint32_t find_common_dominator(uint32_t a, uint32_t b) const; + + const SmallVector &get_preceding_edges(uint32_t block) const + { + auto itr = preceding_edges.find(block); + if (itr != std::end(preceding_edges)) + return itr->second; + else + return empty_vector; + } + + const SmallVector &get_succeeding_edges(uint32_t block) const + { + auto itr = succeeding_edges.find(block); + if (itr != std::end(succeeding_edges)) + return itr->second; + else + return empty_vector; + } + + template + void walk_from(std::unordered_set &seen_blocks, uint32_t block, const Op &op) const + { + if (seen_blocks.count(block)) + return; + seen_blocks.insert(block); + + if (op(block)) + { + for (auto b : get_succeeding_edges(block)) + walk_from(seen_blocks, b, op); + } + } + + uint32_t find_loop_dominator(uint32_t block) const; + + bool node_terminates_control_flow_in_sub_graph(BlockID from, BlockID to) const; + +private: + struct VisitOrder + { + int &get() + { + return v; + } + + const int &get() const + { + return v; + } + + int v = -1; + }; + + Compiler &compiler; + const SPIRFunction &func; + std::unordered_map> preceding_edges; + std::unordered_map> succeeding_edges; + std::unordered_map immediate_dominators; + std::unordered_map visit_order; + SmallVector post_order; + SmallVector empty_vector; + + void add_branch(uint32_t from, uint32_t to); + void build_post_order_visit_order(); + void build_immediate_dominators(); + bool post_order_visit(uint32_t block); + uint32_t visit_count = 0; + + bool is_back_edge(uint32_t to) const; + bool has_visited_forward_edge(uint32_t to) const; +}; + +class DominatorBuilder +{ +public: + DominatorBuilder(const CFG &cfg); + + void add_block(uint32_t block); + uint32_t get_dominator() const + { + return dominator; + } + + void lift_continue_block_dominator(); + +private: + const CFG &cfg; + uint32_t dominator = 0; +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_common.hpp b/ios/include/spirv_cross/spirv_common.hpp new file mode 100644 index 00000000..252d0329 --- /dev/null +++ b/ios/include/spirv_cross/spirv_common.hpp @@ -0,0 +1,1781 @@ +/* + * Copyright 2015-2020 Arm Limited + * + * 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 SPIRV_CROSS_COMMON_HPP +#define SPIRV_CROSS_COMMON_HPP + +#include "spirv.hpp" +#include "spirv_cross_containers.hpp" +#include "spirv_cross_error_handling.hpp" +#include + +// A bit crude, but allows projects which embed SPIRV-Cross statically to +// effectively hide all the symbols from other projects. +// There is a case where we have: +// - Project A links against SPIRV-Cross statically. +// - Project A links against Project B statically. +// - Project B links against SPIRV-Cross statically (might be a different version). +// This leads to a conflict with extremely bizarre results. +// By overriding the namespace in one of the project builds, we can work around this. +// If SPIRV-Cross is embedded in dynamic libraries, +// prefer using -fvisibility=hidden on GCC/Clang instead. +#ifdef SPIRV_CROSS_NAMESPACE_OVERRIDE +#define SPIRV_CROSS_NAMESPACE SPIRV_CROSS_NAMESPACE_OVERRIDE +#else +#define SPIRV_CROSS_NAMESPACE spirv_cross +#endif + +namespace SPIRV_CROSS_NAMESPACE +{ +namespace inner +{ +template +void join_helper(StringStream<> &stream, T &&t) +{ + stream << std::forward(t); +} + +template +void join_helper(StringStream<> &stream, T &&t, Ts &&... ts) +{ + stream << std::forward(t); + join_helper(stream, std::forward(ts)...); +} +} // namespace inner + +class Bitset +{ +public: + Bitset() = default; + explicit inline Bitset(uint64_t lower_) + : lower(lower_) + { + } + + inline bool get(uint32_t bit) const + { + if (bit < 64) + return (lower & (1ull << bit)) != 0; + else + return higher.count(bit) != 0; + } + + inline void set(uint32_t bit) + { + if (bit < 64) + lower |= 1ull << bit; + else + higher.insert(bit); + } + + inline void clear(uint32_t bit) + { + if (bit < 64) + lower &= ~(1ull << bit); + else + higher.erase(bit); + } + + inline uint64_t get_lower() const + { + return lower; + } + + inline void reset() + { + lower = 0; + higher.clear(); + } + + inline void merge_and(const Bitset &other) + { + lower &= other.lower; + std::unordered_set tmp_set; + for (auto &v : higher) + if (other.higher.count(v) != 0) + tmp_set.insert(v); + higher = std::move(tmp_set); + } + + inline void merge_or(const Bitset &other) + { + lower |= other.lower; + for (auto &v : other.higher) + higher.insert(v); + } + + inline bool operator==(const Bitset &other) const + { + if (lower != other.lower) + return false; + + if (higher.size() != other.higher.size()) + return false; + + for (auto &v : higher) + if (other.higher.count(v) == 0) + return false; + + return true; + } + + inline bool operator!=(const Bitset &other) const + { + return !(*this == other); + } + + template + void for_each_bit(const Op &op) const + { + // TODO: Add ctz-based iteration. + for (uint32_t i = 0; i < 64; i++) + { + if (lower & (1ull << i)) + op(i); + } + + if (higher.empty()) + return; + + // Need to enforce an order here for reproducible results, + // but hitting this path should happen extremely rarely, so having this slow path is fine. + SmallVector bits; + bits.reserve(higher.size()); + for (auto &v : higher) + bits.push_back(v); + std::sort(std::begin(bits), std::end(bits)); + + for (auto &v : bits) + op(v); + } + + inline bool empty() const + { + return lower == 0 && higher.empty(); + } + +private: + // The most common bits to set are all lower than 64, + // so optimize for this case. Bits spilling outside 64 go into a slower data structure. + // In almost all cases, higher data structure will not be used. + uint64_t lower = 0; + std::unordered_set higher; +}; + +// Helper template to avoid lots of nasty string temporary munging. +template +std::string join(Ts &&... ts) +{ + StringStream<> stream; + inner::join_helper(stream, std::forward(ts)...); + return stream.str(); +} + +inline std::string merge(const SmallVector &list, const char *between = ", ") +{ + StringStream<> stream; + for (auto &elem : list) + { + stream << elem; + if (&elem != &list.back()) + stream << between; + } + return stream.str(); +} + +// Make sure we don't accidentally call this with float or doubles with SFINAE. +// Have to use the radix-aware overload. +template ::value, int>::type = 0> +inline std::string convert_to_string(const T &t) +{ + return std::to_string(t); +} + +// Allow implementations to set a convenient standard precision +#ifndef SPIRV_CROSS_FLT_FMT +#define SPIRV_CROSS_FLT_FMT "%.32g" +#endif + +// Disable sprintf and strcat warnings. +// We cannot rely on snprintf and family existing because, ..., MSVC. +#if defined(__clang__) || defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + +static inline void fixup_radix_point(char *str, char radix_point) +{ + // Setting locales is a very risky business in multi-threaded program, + // so just fixup locales instead. We only need to care about the radix point. + if (radix_point != '.') + { + while (*str != '\0') + { + if (*str == radix_point) + *str = '.'; + str++; + } + } +} + +inline std::string convert_to_string(float t, char locale_radix_point) +{ + // std::to_string for floating point values is broken. + // Fallback to something more sane. + char buf[64]; + sprintf(buf, SPIRV_CROSS_FLT_FMT, t); + fixup_radix_point(buf, locale_radix_point); + + // Ensure that the literal is float. + if (!strchr(buf, '.') && !strchr(buf, 'e')) + strcat(buf, ".0"); + return buf; +} + +inline std::string convert_to_string(double t, char locale_radix_point) +{ + // std::to_string for floating point values is broken. + // Fallback to something more sane. + char buf[64]; + sprintf(buf, SPIRV_CROSS_FLT_FMT, t); + fixup_radix_point(buf, locale_radix_point); + + // Ensure that the literal is float. + if (!strchr(buf, '.') && !strchr(buf, 'e')) + strcat(buf, ".0"); + return buf; +} + +#if defined(__clang__) || defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning(pop) +#endif + +struct Instruction +{ + uint16_t op = 0; + uint16_t count = 0; + uint32_t offset = 0; + uint32_t length = 0; +}; + +enum Types +{ + TypeNone, + TypeType, + TypeVariable, + TypeConstant, + TypeFunction, + TypeFunctionPrototype, + TypeBlock, + TypeExtension, + TypeExpression, + TypeConstantOp, + TypeCombinedImageSampler, + TypeAccessChain, + TypeUndef, + TypeString, + TypeCount +}; + +template +class TypedID; + +template <> +class TypedID +{ +public: + TypedID() = default; + TypedID(uint32_t id_) + : id(id_) + { + } + + template + TypedID(const TypedID &other) + { + *this = other; + } + + template + TypedID &operator=(const TypedID &other) + { + id = uint32_t(other); + return *this; + } + + // Implicit conversion to u32 is desired here. + // As long as we block implicit conversion between TypedID and TypedID we're good. + operator uint32_t() const + { + return id; + } + + template + operator TypedID() const + { + return TypedID(*this); + } + + bool operator==(const TypedID &other) const + { + return id == other.id; + } + + bool operator!=(const TypedID &other) const + { + return id != other.id; + } + + template + bool operator==(const TypedID &other) const + { + return id == uint32_t(other); + } + + template + bool operator!=(const TypedID &other) const + { + return id != uint32_t(other); + } + +private: + uint32_t id = 0; +}; + +template +class TypedID +{ +public: + TypedID() = default; + TypedID(uint32_t id_) + : id(id_) + { + } + + explicit TypedID(const TypedID &other) + : id(uint32_t(other)) + { + } + + operator uint32_t() const + { + return id; + } + + bool operator==(const TypedID &other) const + { + return id == other.id; + } + + bool operator!=(const TypedID &other) const + { + return id != other.id; + } + + bool operator==(const TypedID &other) const + { + return id == uint32_t(other); + } + + bool operator!=(const TypedID &other) const + { + return id != uint32_t(other); + } + +private: + uint32_t id = 0; +}; + +using VariableID = TypedID; +using TypeID = TypedID; +using ConstantID = TypedID; +using FunctionID = TypedID; +using BlockID = TypedID; +using ID = TypedID; + +// Helper for Variant interface. +struct IVariant +{ + virtual ~IVariant() = default; + virtual IVariant *clone(ObjectPoolBase *pool) = 0; + ID self = 0; +}; + +#define SPIRV_CROSS_DECLARE_CLONE(T) \ + IVariant *clone(ObjectPoolBase *pool) override \ + { \ + return static_cast *>(pool)->allocate(*this); \ + } + +struct SPIRUndef : IVariant +{ + enum + { + type = TypeUndef + }; + + explicit SPIRUndef(TypeID basetype_) + : basetype(basetype_) + { + } + TypeID basetype; + + SPIRV_CROSS_DECLARE_CLONE(SPIRUndef) +}; + +struct SPIRString : IVariant +{ + enum + { + type = TypeString + }; + + explicit SPIRString(std::string str_) + : str(std::move(str_)) + { + } + + std::string str; + + SPIRV_CROSS_DECLARE_CLONE(SPIRString) +}; + +// This type is only used by backends which need to access the combined image and sampler IDs separately after +// the OpSampledImage opcode. +struct SPIRCombinedImageSampler : IVariant +{ + enum + { + type = TypeCombinedImageSampler + }; + SPIRCombinedImageSampler(TypeID type_, VariableID image_, VariableID sampler_) + : combined_type(type_) + , image(image_) + , sampler(sampler_) + { + } + TypeID combined_type; + VariableID image; + VariableID sampler; + + SPIRV_CROSS_DECLARE_CLONE(SPIRCombinedImageSampler) +}; + +struct SPIRConstantOp : IVariant +{ + enum + { + type = TypeConstantOp + }; + + SPIRConstantOp(TypeID result_type, spv::Op op, const uint32_t *args, uint32_t length) + : opcode(op) + , basetype(result_type) + { + arguments.reserve(length); + for (uint32_t i = 0; i < length; i++) + arguments.push_back(args[i]); + } + + spv::Op opcode; + SmallVector arguments; + TypeID basetype; + + SPIRV_CROSS_DECLARE_CLONE(SPIRConstantOp) +}; + +struct SPIRType : IVariant +{ + enum + { + type = TypeType + }; + + enum BaseType + { + Unknown, + Void, + Boolean, + SByte, + UByte, + Short, + UShort, + Int, + UInt, + Int64, + UInt64, + AtomicCounter, + Half, + Float, + Double, + Struct, + Image, + SampledImage, + Sampler, + AccelerationStructure, + RayQuery, + + // Keep internal types at the end. + ControlPointArray, + Char + }; + + // Scalar/vector/matrix support. + BaseType basetype = Unknown; + uint32_t width = 0; + uint32_t vecsize = 1; + uint32_t columns = 1; + + // Arrays, support array of arrays by having a vector of array sizes. + SmallVector array; + + // Array elements can be either specialization constants or specialization ops. + // This array determines how to interpret the array size. + // If an element is true, the element is a literal, + // otherwise, it's an expression, which must be resolved on demand. + // The actual size is not really known until runtime. + SmallVector array_size_literal; + + // Pointers + // Keep track of how many pointer layers we have. + uint32_t pointer_depth = 0; + bool pointer = false; + + spv::StorageClass storage = spv::StorageClassGeneric; + + SmallVector member_types; + + struct ImageType + { + TypeID type; + spv::Dim dim; + bool depth; + bool arrayed; + bool ms; + uint32_t sampled; + spv::ImageFormat format; + spv::AccessQualifier access; + } image; + + // Structs can be declared multiple times if they are used as part of interface blocks. + // We want to detect this so that we only emit the struct definition once. + // Since we cannot rely on OpName to be equal, we need to figure out aliases. + TypeID type_alias = 0; + + // Denotes the type which this type is based on. + // Allows the backend to traverse how a complex type is built up during access chains. + TypeID parent_type = 0; + + // Used in backends to avoid emitting members with conflicting names. + std::unordered_set member_name_cache; + + SPIRV_CROSS_DECLARE_CLONE(SPIRType) +}; + +struct SPIRExtension : IVariant +{ + enum + { + type = TypeExtension + }; + + enum Extension + { + Unsupported, + GLSL, + SPV_debug_info, + SPV_AMD_shader_ballot, + SPV_AMD_shader_explicit_vertex_parameter, + SPV_AMD_shader_trinary_minmax, + SPV_AMD_gcn_shader + }; + + explicit SPIRExtension(Extension ext_) + : ext(ext_) + { + } + + Extension ext; + SPIRV_CROSS_DECLARE_CLONE(SPIRExtension) +}; + +// SPIREntryPoint is not a variant since its IDs are used to decorate OpFunction, +// so in order to avoid conflicts, we can't stick them in the ids array. +struct SPIREntryPoint +{ + SPIREntryPoint(FunctionID self_, spv::ExecutionModel execution_model, const std::string &entry_name) + : self(self_) + , name(entry_name) + , orig_name(entry_name) + , model(execution_model) + { + } + SPIREntryPoint() = default; + + FunctionID self = 0; + std::string name; + std::string orig_name; + SmallVector interface_variables; + + Bitset flags; + struct + { + uint32_t x = 0, y = 0, z = 0; + uint32_t constant = 0; // Workgroup size can be expressed as a constant/spec-constant instead. + } workgroup_size; + uint32_t invocations = 0; + uint32_t output_vertices = 0; + spv::ExecutionModel model = spv::ExecutionModelMax; + bool geometry_passthrough = false; +}; + +struct SPIRExpression : IVariant +{ + enum + { + type = TypeExpression + }; + + // Only created by the backend target to avoid creating tons of temporaries. + SPIRExpression(std::string expr, TypeID expression_type_, bool immutable_) + : expression(move(expr)) + , expression_type(expression_type_) + , immutable(immutable_) + { + } + + // If non-zero, prepend expression with to_expression(base_expression). + // Used in amortizing multiple calls to to_expression() + // where in certain cases that would quickly force a temporary when not needed. + ID base_expression = 0; + + std::string expression; + TypeID expression_type = 0; + + // If this expression is a forwarded load, + // allow us to reference the original variable. + ID loaded_from = 0; + + // If this expression will never change, we can avoid lots of temporaries + // in high level source. + // An expression being immutable can be speculative, + // it is assumed that this is true almost always. + bool immutable = false; + + // Before use, this expression must be transposed. + // This is needed for targets which don't support row_major layouts. + bool need_transpose = false; + + // Whether or not this is an access chain expression. + bool access_chain = false; + + // A list of expressions which this expression depends on. + SmallVector expression_dependencies; + + // By reading this expression, we implicitly read these expressions as well. + // Used by access chain Store and Load since we read multiple expressions in this case. + SmallVector implied_read_expressions; + + SPIRV_CROSS_DECLARE_CLONE(SPIRExpression) +}; + +struct SPIRFunctionPrototype : IVariant +{ + enum + { + type = TypeFunctionPrototype + }; + + explicit SPIRFunctionPrototype(TypeID return_type_) + : return_type(return_type_) + { + } + + TypeID return_type; + SmallVector parameter_types; + + SPIRV_CROSS_DECLARE_CLONE(SPIRFunctionPrototype) +}; + +struct SPIRBlock : IVariant +{ + enum + { + type = TypeBlock + }; + + enum Terminator + { + Unknown, + Direct, // Emit next block directly without a particular condition. + + Select, // Block ends with an if/else block. + MultiSelect, // Block ends with switch statement. + + Return, // Block ends with return. + Unreachable, // Noop + Kill // Discard + }; + + enum Merge + { + MergeNone, + MergeLoop, + MergeSelection + }; + + enum Hints + { + HintNone, + HintUnroll, + HintDontUnroll, + HintFlatten, + HintDontFlatten + }; + + enum Method + { + MergeToSelectForLoop, + MergeToDirectForLoop, + MergeToSelectContinueForLoop + }; + + enum ContinueBlockType + { + ContinueNone, + + // Continue block is branchless and has at least one instruction. + ForLoop, + + // Noop continue block. + WhileLoop, + + // Continue block is conditional. + DoWhileLoop, + + // Highly unlikely that anything will use this, + // since it is really awkward/impossible to express in GLSL. + ComplexLoop + }; + + enum + { + NoDominator = 0xffffffffu + }; + + Terminator terminator = Unknown; + Merge merge = MergeNone; + Hints hint = HintNone; + BlockID next_block = 0; + BlockID merge_block = 0; + BlockID continue_block = 0; + + ID return_value = 0; // If 0, return nothing (void). + ID condition = 0; + BlockID true_block = 0; + BlockID false_block = 0; + BlockID default_block = 0; + + SmallVector ops; + + struct Phi + { + ID local_variable; // flush local variable ... + BlockID parent; // If we're in from_block and want to branch into this block ... + VariableID function_variable; // to this function-global "phi" variable first. + }; + + // Before entering this block flush out local variables to magical "phi" variables. + SmallVector phi_variables; + + // Declare these temporaries before beginning the block. + // Used for handling complex continue blocks which have side effects. + SmallVector> declare_temporary; + + // Declare these temporaries, but only conditionally if this block turns out to be + // a complex loop header. + SmallVector> potential_declare_temporary; + + struct Case + { + uint32_t value; + BlockID block; + }; + SmallVector cases; + + // If we have tried to optimize code for this block but failed, + // keep track of this. + bool disable_block_optimization = false; + + // If the continue block is complex, fallback to "dumb" for loops. + bool complex_continue = false; + + // Do we need a ladder variable to defer breaking out of a loop construct after a switch block? + bool need_ladder_break = false; + + // If marked, we have explicitly handled Phi from this block, so skip any flushes related to that on a branch. + // Used to handle an edge case with switch and case-label fallthrough where fall-through writes to Phi. + BlockID ignore_phi_from_block = 0; + + // The dominating block which this block might be within. + // Used in continue; blocks to determine if we really need to write continue. + BlockID loop_dominator = 0; + + // All access to these variables are dominated by this block, + // so before branching anywhere we need to make sure that we declare these variables. + SmallVector dominated_variables; + + // These are variables which should be declared in a for loop header, if we + // fail to use a classic for-loop, + // we remove these variables, and fall back to regular variables outside the loop. + SmallVector loop_variables; + + // Some expressions are control-flow dependent, i.e. any instruction which relies on derivatives or + // sub-group-like operations. + // Make sure that we only use these expressions in the original block. + SmallVector invalidate_expressions; + + SPIRV_CROSS_DECLARE_CLONE(SPIRBlock) +}; + +struct SPIRFunction : IVariant +{ + enum + { + type = TypeFunction + }; + + SPIRFunction(TypeID return_type_, TypeID function_type_) + : return_type(return_type_) + , function_type(function_type_) + { + } + + struct Parameter + { + TypeID type; + ID id; + uint32_t read_count; + uint32_t write_count; + + // Set to true if this parameter aliases a global variable, + // used mostly in Metal where global variables + // have to be passed down to functions as regular arguments. + // However, for this kind of variable, we should not care about + // read and write counts as access to the function arguments + // is not local to the function in question. + bool alias_global_variable; + }; + + // When calling a function, and we're remapping separate image samplers, + // resolve these arguments into combined image samplers and pass them + // as additional arguments in this order. + // It gets more complicated as functions can pull in their own globals + // and combine them with parameters, + // so we need to distinguish if something is local parameter index + // or a global ID. + struct CombinedImageSamplerParameter + { + VariableID id; + VariableID image_id; + VariableID sampler_id; + bool global_image; + bool global_sampler; + bool depth; + }; + + TypeID return_type; + TypeID function_type; + SmallVector arguments; + + // Can be used by backends to add magic arguments. + // Currently used by combined image/sampler implementation. + + SmallVector shadow_arguments; + SmallVector local_variables; + BlockID entry_block = 0; + SmallVector blocks; + SmallVector combined_parameters; + + struct EntryLine + { + uint32_t file_id = 0; + uint32_t line_literal = 0; + }; + EntryLine entry_line; + + void add_local_variable(VariableID id) + { + local_variables.push_back(id); + } + + void add_parameter(TypeID parameter_type, ID id, bool alias_global_variable = false) + { + // Arguments are read-only until proven otherwise. + arguments.push_back({ parameter_type, id, 0u, 0u, alias_global_variable }); + } + + // Hooks to be run when the function returns. + // Mostly used for lowering internal data structures onto flattened structures. + // Need to defer this, because they might rely on things which change during compilation. + // Intentionally not a small vector, this one is rare, and std::function can be large. + Vector> fixup_hooks_out; + + // Hooks to be run when the function begins. + // Mostly used for populating internal data structures from flattened structures. + // Need to defer this, because they might rely on things which change during compilation. + // Intentionally not a small vector, this one is rare, and std::function can be large. + Vector> fixup_hooks_in; + + // On function entry, make sure to copy a constant array into thread addr space to work around + // the case where we are passing a constant array by value to a function on backends which do not + // consider arrays value types. + SmallVector constant_arrays_needed_on_stack; + + bool active = false; + bool flush_undeclared = true; + bool do_combined_parameters = true; + + SPIRV_CROSS_DECLARE_CLONE(SPIRFunction) +}; + +struct SPIRAccessChain : IVariant +{ + enum + { + type = TypeAccessChain + }; + + SPIRAccessChain(TypeID basetype_, spv::StorageClass storage_, std::string base_, std::string dynamic_index_, + int32_t static_index_) + : basetype(basetype_) + , storage(storage_) + , base(std::move(base_)) + , dynamic_index(std::move(dynamic_index_)) + , static_index(static_index_) + { + } + + // The access chain represents an offset into a buffer. + // Some backends need more complicated handling of access chains to be able to use buffers, like HLSL + // which has no usable buffer type ala GLSL SSBOs. + // StructuredBuffer is too limited, so our only option is to deal with ByteAddressBuffer which works with raw addresses. + + TypeID basetype; + spv::StorageClass storage; + std::string base; + std::string dynamic_index; + int32_t static_index; + + VariableID loaded_from = 0; + uint32_t matrix_stride = 0; + uint32_t array_stride = 0; + bool row_major_matrix = false; + bool immutable = false; + + // By reading this expression, we implicitly read these expressions as well. + // Used by access chain Store and Load since we read multiple expressions in this case. + SmallVector implied_read_expressions; + + SPIRV_CROSS_DECLARE_CLONE(SPIRAccessChain) +}; + +struct SPIRVariable : IVariant +{ + enum + { + type = TypeVariable + }; + + SPIRVariable() = default; + SPIRVariable(TypeID basetype_, spv::StorageClass storage_, ID initializer_ = 0, VariableID basevariable_ = 0) + : basetype(basetype_) + , storage(storage_) + , initializer(initializer_) + , basevariable(basevariable_) + { + } + + TypeID basetype = 0; + spv::StorageClass storage = spv::StorageClassGeneric; + uint32_t decoration = 0; + ID initializer = 0; + VariableID basevariable = 0; + + SmallVector dereference_chain; + bool compat_builtin = false; + + // If a variable is shadowed, we only statically assign to it + // and never actually emit a statement for it. + // When we read the variable as an expression, just forward + // shadowed_id as the expression. + bool statically_assigned = false; + ID static_expression = 0; + + // Temporaries which can remain forwarded as long as this variable is not modified. + SmallVector dependees; + bool forwardable = true; + + bool deferred_declaration = false; + bool phi_variable = false; + + // Used to deal with Phi variable flushes. See flush_phi(). + bool allocate_temporary_copy = false; + + bool remapped_variable = false; + uint32_t remapped_components = 0; + + // The block which dominates all access to this variable. + BlockID dominator = 0; + // If true, this variable is a loop variable, when accessing the variable + // outside a loop, + // we should statically forward it. + bool loop_variable = false; + // Set to true while we're inside the for loop. + bool loop_variable_enable = false; + + SPIRFunction::Parameter *parameter = nullptr; + + SPIRV_CROSS_DECLARE_CLONE(SPIRVariable) +}; + +struct SPIRConstant : IVariant +{ + enum + { + type = TypeConstant + }; + + union Constant { + uint32_t u32; + int32_t i32; + float f32; + + uint64_t u64; + int64_t i64; + double f64; + }; + + struct ConstantVector + { + Constant r[4]; + // If != 0, this element is a specialization constant, and we should keep track of it as such. + ID id[4]; + uint32_t vecsize = 1; + + ConstantVector() + { + memset(r, 0, sizeof(r)); + } + }; + + struct ConstantMatrix + { + ConstantVector c[4]; + // If != 0, this column is a specialization constant, and we should keep track of it as such. + ID id[4]; + uint32_t columns = 1; + }; + + static inline float f16_to_f32(uint16_t u16_value) + { + // Based on the GLM implementation. + int s = (u16_value >> 15) & 0x1; + int e = (u16_value >> 10) & 0x1f; + int m = (u16_value >> 0) & 0x3ff; + + union { + float f32; + uint32_t u32; + } u; + + if (e == 0) + { + if (m == 0) + { + u.u32 = uint32_t(s) << 31; + return u.f32; + } + else + { + while ((m & 0x400) == 0) + { + m <<= 1; + e--; + } + + e++; + m &= ~0x400; + } + } + else if (e == 31) + { + if (m == 0) + { + u.u32 = (uint32_t(s) << 31) | 0x7f800000u; + return u.f32; + } + else + { + u.u32 = (uint32_t(s) << 31) | 0x7f800000u | (m << 13); + return u.f32; + } + } + + e += 127 - 15; + m <<= 13; + u.u32 = (uint32_t(s) << 31) | (e << 23) | m; + return u.f32; + } + + inline uint32_t specialization_constant_id(uint32_t col, uint32_t row) const + { + return m.c[col].id[row]; + } + + inline uint32_t specialization_constant_id(uint32_t col) const + { + return m.id[col]; + } + + inline uint32_t scalar(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].u32; + } + + inline int16_t scalar_i16(uint32_t col = 0, uint32_t row = 0) const + { + return int16_t(m.c[col].r[row].u32 & 0xffffu); + } + + inline uint16_t scalar_u16(uint32_t col = 0, uint32_t row = 0) const + { + return uint16_t(m.c[col].r[row].u32 & 0xffffu); + } + + inline int8_t scalar_i8(uint32_t col = 0, uint32_t row = 0) const + { + return int8_t(m.c[col].r[row].u32 & 0xffu); + } + + inline uint8_t scalar_u8(uint32_t col = 0, uint32_t row = 0) const + { + return uint8_t(m.c[col].r[row].u32 & 0xffu); + } + + inline float scalar_f16(uint32_t col = 0, uint32_t row = 0) const + { + return f16_to_f32(scalar_u16(col, row)); + } + + inline float scalar_f32(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].f32; + } + + inline int32_t scalar_i32(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].i32; + } + + inline double scalar_f64(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].f64; + } + + inline int64_t scalar_i64(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].i64; + } + + inline uint64_t scalar_u64(uint32_t col = 0, uint32_t row = 0) const + { + return m.c[col].r[row].u64; + } + + inline const ConstantVector &vector() const + { + return m.c[0]; + } + + inline uint32_t vector_size() const + { + return m.c[0].vecsize; + } + + inline uint32_t columns() const + { + return m.columns; + } + + inline void make_null(const SPIRType &constant_type_) + { + m = {}; + m.columns = constant_type_.columns; + for (auto &c : m.c) + c.vecsize = constant_type_.vecsize; + } + + inline bool constant_is_null() const + { + if (specialization) + return false; + if (!subconstants.empty()) + return false; + + for (uint32_t col = 0; col < columns(); col++) + for (uint32_t row = 0; row < vector_size(); row++) + if (scalar_u64(col, row) != 0) + return false; + + return true; + } + + explicit SPIRConstant(uint32_t constant_type_) + : constant_type(constant_type_) + { + } + + SPIRConstant() = default; + + SPIRConstant(TypeID constant_type_, const uint32_t *elements, uint32_t num_elements, bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + subconstants.reserve(num_elements); + for (uint32_t i = 0; i < num_elements; i++) + subconstants.push_back(elements[i]); + specialization = specialized; + } + + // Construct scalar (32-bit). + SPIRConstant(TypeID constant_type_, uint32_t v0, bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + m.c[0].r[0].u32 = v0; + m.c[0].vecsize = 1; + m.columns = 1; + } + + // Construct scalar (64-bit). + SPIRConstant(TypeID constant_type_, uint64_t v0, bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + m.c[0].r[0].u64 = v0; + m.c[0].vecsize = 1; + m.columns = 1; + } + + // Construct vectors and matrices. + SPIRConstant(TypeID constant_type_, const SPIRConstant *const *vector_elements, uint32_t num_elements, + bool specialized) + : constant_type(constant_type_) + , specialization(specialized) + { + bool matrix = vector_elements[0]->m.c[0].vecsize > 1; + + if (matrix) + { + m.columns = num_elements; + + for (uint32_t i = 0; i < num_elements; i++) + { + m.c[i] = vector_elements[i]->m.c[0]; + if (vector_elements[i]->specialization) + m.id[i] = vector_elements[i]->self; + } + } + else + { + m.c[0].vecsize = num_elements; + m.columns = 1; + + for (uint32_t i = 0; i < num_elements; i++) + { + m.c[0].r[i] = vector_elements[i]->m.c[0].r[0]; + if (vector_elements[i]->specialization) + m.c[0].id[i] = vector_elements[i]->self; + } + } + } + + TypeID constant_type = 0; + ConstantMatrix m; + + // If this constant is a specialization constant (i.e. created with OpSpecConstant*). + bool specialization = false; + // If this constant is used as an array length which creates specialization restrictions on some backends. + bool is_used_as_array_length = false; + + // If true, this is a LUT, and should always be declared in the outer scope. + bool is_used_as_lut = false; + + // For composites which are constant arrays, etc. + SmallVector subconstants; + + // Non-Vulkan GLSL, HLSL and sometimes MSL emits defines for each specialization constant, + // and uses them to initialize the constant. This allows the user + // to still be able to specialize the value by supplying corresponding + // preprocessor directives before compiling the shader. + std::string specialization_constant_macro_name; + + SPIRV_CROSS_DECLARE_CLONE(SPIRConstant) +}; + +// Variants have a very specific allocation scheme. +struct ObjectPoolGroup +{ + std::unique_ptr pools[TypeCount]; +}; + +class Variant +{ +public: + explicit Variant(ObjectPoolGroup *group_) + : group(group_) + { + } + + ~Variant() + { + if (holder) + group->pools[type]->free_opaque(holder); + } + + // Marking custom move constructor as noexcept is important. + Variant(Variant &&other) SPIRV_CROSS_NOEXCEPT + { + *this = std::move(other); + } + + // We cannot copy from other variant without our own pool group. + // Have to explicitly copy. + Variant(const Variant &variant) = delete; + + // Marking custom move constructor as noexcept is important. + Variant &operator=(Variant &&other) SPIRV_CROSS_NOEXCEPT + { + if (this != &other) + { + if (holder) + group->pools[type]->free_opaque(holder); + holder = other.holder; + group = other.group; + type = other.type; + allow_type_rewrite = other.allow_type_rewrite; + + other.holder = nullptr; + other.type = TypeNone; + } + return *this; + } + + // This copy/clone should only be called in the Compiler constructor. + // If this is called inside ::compile(), we invalidate any references we took higher in the stack. + // This should never happen. + Variant &operator=(const Variant &other) + { +//#define SPIRV_CROSS_COPY_CONSTRUCTOR_SANITIZE +#ifdef SPIRV_CROSS_COPY_CONSTRUCTOR_SANITIZE + abort(); +#endif + if (this != &other) + { + if (holder) + group->pools[type]->free_opaque(holder); + + if (other.holder) + holder = other.holder->clone(group->pools[other.type].get()); + else + holder = nullptr; + + type = other.type; + allow_type_rewrite = other.allow_type_rewrite; + } + return *this; + } + + void set(IVariant *val, Types new_type) + { + if (holder) + group->pools[type]->free_opaque(holder); + holder = nullptr; + + if (!allow_type_rewrite && type != TypeNone && type != new_type) + { + if (val) + group->pools[new_type]->free_opaque(val); + SPIRV_CROSS_THROW("Overwriting a variant with new type."); + } + + holder = val; + type = new_type; + allow_type_rewrite = false; + } + + template + T *allocate_and_set(Types new_type, Ts &&... ts) + { + T *val = static_cast &>(*group->pools[new_type]).allocate(std::forward(ts)...); + set(val, new_type); + return val; + } + + template + T &get() + { + if (!holder) + SPIRV_CROSS_THROW("nullptr"); + if (static_cast(T::type) != type) + SPIRV_CROSS_THROW("Bad cast"); + return *static_cast(holder); + } + + template + const T &get() const + { + if (!holder) + SPIRV_CROSS_THROW("nullptr"); + if (static_cast(T::type) != type) + SPIRV_CROSS_THROW("Bad cast"); + return *static_cast(holder); + } + + Types get_type() const + { + return type; + } + + ID get_id() const + { + return holder ? holder->self : ID(0); + } + + bool empty() const + { + return !holder; + } + + void reset() + { + if (holder) + group->pools[type]->free_opaque(holder); + holder = nullptr; + type = TypeNone; + } + + void set_allow_type_rewrite() + { + allow_type_rewrite = true; + } + +private: + ObjectPoolGroup *group = nullptr; + IVariant *holder = nullptr; + Types type = TypeNone; + bool allow_type_rewrite = false; +}; + +template +T &variant_get(Variant &var) +{ + return var.get(); +} + +template +const T &variant_get(const Variant &var) +{ + return var.get(); +} + +template +T &variant_set(Variant &var, P &&... args) +{ + auto *ptr = var.allocate_and_set(static_cast(T::type), std::forward

(args)...); + return *ptr; +} + +struct AccessChainMeta +{ + uint32_t storage_physical_type = 0; + bool need_transpose = false; + bool storage_is_packed = false; + bool storage_is_invariant = false; +}; + +enum ExtendedDecorations +{ + // Marks if a buffer block is re-packed, i.e. member declaration might be subject to PhysicalTypeID remapping and padding. + SPIRVCrossDecorationBufferBlockRepacked = 0, + + // A type in a buffer block might be declared with a different physical type than the logical type. + // If this is not set, PhysicalTypeID == the SPIR-V type as declared. + SPIRVCrossDecorationPhysicalTypeID, + + // Marks if the physical type is to be declared with tight packing rules, i.e. packed_floatN on MSL and friends. + // If this is set, PhysicalTypeID might also be set. It can be set to same as logical type if all we're doing + // is converting float3 to packed_float3 for example. + // If this is marked on a struct, it means the struct itself must use only Packed types for all its members. + SPIRVCrossDecorationPhysicalTypePacked, + + // The padding in bytes before declaring this struct member. + // If used on a struct type, marks the target size of a struct. + SPIRVCrossDecorationPaddingTarget, + + SPIRVCrossDecorationInterfaceMemberIndex, + SPIRVCrossDecorationInterfaceOrigID, + SPIRVCrossDecorationResourceIndexPrimary, + // Used for decorations like resource indices for samplers when part of combined image samplers. + // A variable might need to hold two resource indices in this case. + SPIRVCrossDecorationResourceIndexSecondary, + // Used for resource indices for multiplanar images when part of combined image samplers. + SPIRVCrossDecorationResourceIndexTertiary, + SPIRVCrossDecorationResourceIndexQuaternary, + + // Marks a buffer block for using explicit offsets (GLSL/HLSL). + SPIRVCrossDecorationExplicitOffset, + + // Apply to a variable in the Input storage class; marks it as holding the base group passed to vkCmdDispatchBase(). + // In MSL, this is used to adjust the WorkgroupId and GlobalInvocationId variables. + SPIRVCrossDecorationBuiltInDispatchBase, + + // Apply to a variable that is a function parameter; marks it as being a "dynamic" + // combined image-sampler. In MSL, this is used when a function parameter might hold + // either a regular combined image-sampler or one that has an attached sampler + // Y'CbCr conversion. + SPIRVCrossDecorationDynamicImageSampler, + + SPIRVCrossDecorationCount +}; + +struct Meta +{ + struct Decoration + { + std::string alias; + std::string qualified_alias; + std::string hlsl_semantic; + Bitset decoration_flags; + spv::BuiltIn builtin_type = spv::BuiltInMax; + uint32_t location = 0; + uint32_t component = 0; + uint32_t set = 0; + uint32_t binding = 0; + uint32_t offset = 0; + uint32_t xfb_buffer = 0; + uint32_t xfb_stride = 0; + uint32_t array_stride = 0; + uint32_t matrix_stride = 0; + uint32_t input_attachment = 0; + uint32_t spec_id = 0; + uint32_t index = 0; + spv::FPRoundingMode fp_rounding_mode = spv::FPRoundingModeMax; + bool builtin = false; + + struct Extended + { + Extended() + { + // MSVC 2013 workaround to init like this. + for (auto &v : values) + v = 0; + } + + Bitset flags; + uint32_t values[SPIRVCrossDecorationCount]; + } extended; + }; + + Decoration decoration; + + // Intentionally not a SmallVector. Decoration is large and somewhat rare. + Vector members; + + std::unordered_map decoration_word_offset; + + // For SPV_GOOGLE_hlsl_functionality1. + bool hlsl_is_magic_counter_buffer = false; + // ID for the sibling counter buffer. + uint32_t hlsl_magic_counter_buffer = 0; +}; + +// A user callback that remaps the type of any variable. +// var_name is the declared name of the variable. +// name_of_type is the textual name of the type which will be used in the code unless written to by the callback. +using VariableTypeRemapCallback = + std::function; + +class Hasher +{ +public: + inline void u32(uint32_t value) + { + h = (h * 0x100000001b3ull) ^ value; + } + + inline uint64_t get() const + { + return h; + } + +private: + uint64_t h = 0xcbf29ce484222325ull; +}; + +static inline bool type_is_floating_point(const SPIRType &type) +{ + return type.basetype == SPIRType::Half || type.basetype == SPIRType::Float || type.basetype == SPIRType::Double; +} + +static inline bool type_is_integral(const SPIRType &type) +{ + return type.basetype == SPIRType::SByte || type.basetype == SPIRType::UByte || type.basetype == SPIRType::Short || + type.basetype == SPIRType::UShort || type.basetype == SPIRType::Int || type.basetype == SPIRType::UInt || + type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64; +} + +static inline SPIRType::BaseType to_signed_basetype(uint32_t width) +{ + switch (width) + { + case 8: + return SPIRType::SByte; + case 16: + return SPIRType::Short; + case 32: + return SPIRType::Int; + case 64: + return SPIRType::Int64; + default: + SPIRV_CROSS_THROW("Invalid bit width."); + } +} + +static inline SPIRType::BaseType to_unsigned_basetype(uint32_t width) +{ + switch (width) + { + case 8: + return SPIRType::UByte; + case 16: + return SPIRType::UShort; + case 32: + return SPIRType::UInt; + case 64: + return SPIRType::UInt64; + default: + SPIRV_CROSS_THROW("Invalid bit width."); + } +} + +// Returns true if an arithmetic operation does not change behavior depending on signedness. +static inline bool opcode_is_sign_invariant(spv::Op opcode) +{ + switch (opcode) + { + case spv::OpIEqual: + case spv::OpINotEqual: + case spv::OpISub: + case spv::OpIAdd: + case spv::OpIMul: + case spv::OpShiftLeftLogical: + case spv::OpBitwiseOr: + case spv::OpBitwiseXor: + case spv::OpBitwiseAnd: + return true; + + default: + return false; + } +} + +struct SetBindingPair +{ + uint32_t desc_set; + uint32_t binding; + + inline bool operator==(const SetBindingPair &other) const + { + return desc_set == other.desc_set && binding == other.binding; + } + + inline bool operator<(const SetBindingPair &other) const + { + return desc_set < other.desc_set || (desc_set == other.desc_set && binding < other.binding); + } +}; + +struct StageSetBinding +{ + spv::ExecutionModel model; + uint32_t desc_set; + uint32_t binding; + + inline bool operator==(const StageSetBinding &other) const + { + return model == other.model && desc_set == other.desc_set && binding == other.binding; + } +}; + +struct InternalHasher +{ + inline size_t operator()(const SetBindingPair &value) const + { + // Quality of hash doesn't really matter here. + auto hash_set = std::hash()(value.desc_set); + auto hash_binding = std::hash()(value.binding); + return (hash_set * 0x10001b31) ^ hash_binding; + } + + inline size_t operator()(const StageSetBinding &value) const + { + // Quality of hash doesn't really matter here. + auto hash_model = std::hash()(value.model); + auto hash_set = std::hash()(value.desc_set); + auto tmp_hash = (hash_model * 0x10001b31) ^ hash_set; + return (tmp_hash * 0x10001b31) ^ value.binding; + } +}; + +// Special constant used in a {MSL,HLSL}ResourceBinding desc_set +// element to indicate the bindings for the push constants. +static const uint32_t ResourceBindingPushConstantDescriptorSet = ~(0u); + +// Special constant used in a {MSL,HLSL}ResourceBinding binding +// element to indicate the bindings for the push constants. +static const uint32_t ResourceBindingPushConstantBinding = 0; +} // namespace SPIRV_CROSS_NAMESPACE + +namespace std +{ +template +struct hash> +{ + size_t operator()(const SPIRV_CROSS_NAMESPACE::TypedID &value) const + { + return std::hash()(value); + } +}; +} // namespace std + +#endif diff --git a/ios/include/spirv_cross/spirv_cpp.hpp b/ios/include/spirv_cross/spirv_cpp.hpp new file mode 100644 index 00000000..e78d0369 --- /dev/null +++ b/ios/include/spirv_cross/spirv_cpp.hpp @@ -0,0 +1,86 @@ +/* + * Copyright 2015-2020 Arm Limited + * + * 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 SPIRV_CROSS_CPP_HPP +#define SPIRV_CROSS_CPP_HPP + +#include "spirv_glsl.hpp" +#include + +namespace SPIRV_CROSS_NAMESPACE +{ +class CompilerCPP : public CompilerGLSL +{ +public: + explicit CompilerCPP(std::vector spirv_) + : CompilerGLSL(std::move(spirv_)) + { + } + + CompilerCPP(const uint32_t *ir_, size_t word_count) + : CompilerGLSL(ir_, word_count) + { + } + + explicit CompilerCPP(const ParsedIR &ir_) + : CompilerGLSL(ir_) + { + } + + explicit CompilerCPP(ParsedIR &&ir_) + : CompilerGLSL(std::move(ir_)) + { + } + + std::string compile() override; + + // Sets a custom symbol name that can override + // spirv_cross_get_interface. + // + // Useful when several shader interfaces are linked + // statically into the same binary. + void set_interface_name(std::string name) + { + interface_name = std::move(name); + } + +private: + void emit_header() override; + void emit_c_linkage(); + void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override; + + void emit_resources(); + void emit_buffer_block(const SPIRVariable &type) override; + void emit_push_constant_block(const SPIRVariable &var) override; + void emit_interface_block(const SPIRVariable &type); + void emit_block_chain(SPIRBlock &block); + void emit_uniform(const SPIRVariable &var) override; + void emit_shared(const SPIRVariable &var); + void emit_block_struct(SPIRType &type); + std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id) override; + + std::string argument_decl(const SPIRFunction::Parameter &arg); + + SmallVector resource_registrations; + std::string impl_type; + std::string resource_type; + uint32_t shared_counter = 0; + + std::string interface_name; +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_cross.hpp b/ios/include/spirv_cross/spirv_cross.hpp new file mode 100644 index 00000000..373f9976 --- /dev/null +++ b/ios/include/spirv_cross/spirv_cross.hpp @@ -0,0 +1,1055 @@ +/* + * Copyright 2015-2020 Arm Limited + * + * 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 SPIRV_CROSS_HPP +#define SPIRV_CROSS_HPP + +#include "spirv.hpp" +#include "spirv_cfg.hpp" +#include "spirv_cross_parsed_ir.hpp" + +namespace SPIRV_CROSS_NAMESPACE +{ +struct Resource +{ + // Resources are identified with their SPIR-V ID. + // This is the ID of the OpVariable. + ID id; + + // The type ID of the variable which includes arrays and all type modifications. + // This type ID is not suitable for parsing OpMemberDecoration of a struct and other decorations in general + // since these modifications typically happen on the base_type_id. + TypeID type_id; + + // The base type of the declared resource. + // This type is the base type which ignores pointers and arrays of the type_id. + // This is mostly useful to parse decorations of the underlying type. + // base_type_id can also be obtained with get_type(get_type(type_id).self). + TypeID base_type_id; + + // The declared name (OpName) of the resource. + // For Buffer blocks, the name actually reflects the externally + // visible Block name. + // + // This name can be retrieved again by using either + // get_name(id) or get_name(base_type_id) depending if it's a buffer block or not. + // + // This name can be an empty string in which case get_fallback_name(id) can be + // used which obtains a suitable fallback identifier for an ID. + std::string name; +}; + +struct ShaderResources +{ + SmallVector uniform_buffers; + SmallVector storage_buffers; + SmallVector stage_inputs; + SmallVector stage_outputs; + SmallVector subpass_inputs; + SmallVector storage_images; + SmallVector sampled_images; + SmallVector atomic_counters; + SmallVector acceleration_structures; + + // There can only be one push constant block, + // but keep the vector in case this restriction is lifted in the future. + SmallVector push_constant_buffers; + + // For Vulkan GLSL and HLSL source, + // these correspond to separate texture2D and samplers respectively. + SmallVector separate_images; + SmallVector separate_samplers; +}; + +struct CombinedImageSampler +{ + // The ID of the sampler2D variable. + VariableID combined_id; + // The ID of the texture2D variable. + VariableID image_id; + // The ID of the sampler variable. + VariableID sampler_id; +}; + +struct SpecializationConstant +{ + // The ID of the specialization constant. + ConstantID id; + // The constant ID of the constant, used in Vulkan during pipeline creation. + uint32_t constant_id; +}; + +struct BufferRange +{ + unsigned index; + size_t offset; + size_t range; +}; + +enum BufferPackingStandard +{ + BufferPackingStd140, + BufferPackingStd430, + BufferPackingStd140EnhancedLayout, + BufferPackingStd430EnhancedLayout, + BufferPackingHLSLCbuffer, + BufferPackingHLSLCbufferPackOffset, + BufferPackingScalar, + BufferPackingScalarEnhancedLayout +}; + +struct EntryPoint +{ + std::string name; + spv::ExecutionModel execution_model; +}; + +class Compiler +{ +public: + friend class CFG; + friend class DominatorBuilder; + + // The constructor takes a buffer of SPIR-V words and parses it. + // It will create its own parser, parse the SPIR-V and move the parsed IR + // as if you had called the constructors taking ParsedIR directly. + explicit Compiler(std::vector ir); + Compiler(const uint32_t *ir, size_t word_count); + + // This is more modular. We can also consume a ParsedIR structure directly, either as a move, or copy. + // With copy, we can reuse the same parsed IR for multiple Compiler instances. + explicit Compiler(const ParsedIR &ir); + explicit Compiler(ParsedIR &&ir); + + virtual ~Compiler() = default; + + // After parsing, API users can modify the SPIR-V via reflection and call this + // to disassemble the SPIR-V into the desired langauage. + // Sub-classes actually implement this. + virtual std::string compile(); + + // Gets the identifier (OpName) of an ID. If not defined, an empty string will be returned. + const std::string &get_name(ID id) const; + + // Applies a decoration to an ID. Effectively injects OpDecorate. + void set_decoration(ID id, spv::Decoration decoration, uint32_t argument = 0); + void set_decoration_string(ID id, spv::Decoration decoration, const std::string &argument); + + // Overrides the identifier OpName of an ID. + // Identifiers beginning with underscores or identifiers which contain double underscores + // are reserved by the implementation. + void set_name(ID id, const std::string &name); + + // Gets a bitmask for the decorations which are applied to ID. + // I.e. (1ull << spv::DecorationFoo) | (1ull << spv::DecorationBar) + const Bitset &get_decoration_bitset(ID id) const; + + // Returns whether the decoration has been applied to the ID. + bool has_decoration(ID id, spv::Decoration decoration) const; + + // Gets the value for decorations which take arguments. + // If the decoration is a boolean (i.e. spv::DecorationNonWritable), + // 1 will be returned. + // If decoration doesn't exist or decoration is not recognized, + // 0 will be returned. + uint32_t get_decoration(ID id, spv::Decoration decoration) const; + const std::string &get_decoration_string(ID id, spv::Decoration decoration) const; + + // Removes the decoration for an ID. + void unset_decoration(ID id, spv::Decoration decoration); + + // Gets the SPIR-V type associated with ID. + // Mostly used with Resource::type_id and Resource::base_type_id to parse the underlying type of a resource. + const SPIRType &get_type(TypeID id) const; + + // Gets the SPIR-V type of a variable. + const SPIRType &get_type_from_variable(VariableID id) const; + + // Gets the underlying storage class for an OpVariable. + spv::StorageClass get_storage_class(VariableID id) const; + + // If get_name() is an empty string, get the fallback name which will be used + // instead in the disassembled source. + virtual const std::string get_fallback_name(ID id) const; + + // If get_name() of a Block struct is an empty string, get the fallback name. + // This needs to be per-variable as multiple variables can use the same block type. + virtual const std::string get_block_fallback_name(VariableID id) const; + + // Given an OpTypeStruct in ID, obtain the identifier for member number "index". + // This may be an empty string. + const std::string &get_member_name(TypeID id, uint32_t index) const; + + // Given an OpTypeStruct in ID, obtain the OpMemberDecoration for member number "index". + uint32_t get_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const; + const std::string &get_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration) const; + + // Sets the member identifier for OpTypeStruct ID, member number "index". + void set_member_name(TypeID id, uint32_t index, const std::string &name); + + // Returns the qualified member identifier for OpTypeStruct ID, member number "index", + // or an empty string if no qualified alias exists + const std::string &get_member_qualified_name(TypeID type_id, uint32_t index) const; + + // Gets the decoration mask for a member of a struct, similar to get_decoration_mask. + const Bitset &get_member_decoration_bitset(TypeID id, uint32_t index) const; + + // Returns whether the decoration has been applied to a member of a struct. + bool has_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const; + + // Similar to set_decoration, but for struct members. + void set_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration, uint32_t argument = 0); + void set_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration, + const std::string &argument); + + // Unsets a member decoration, similar to unset_decoration. + void unset_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration); + + // Gets the fallback name for a member, similar to get_fallback_name. + virtual const std::string get_fallback_member_name(uint32_t index) const + { + return join("_", index); + } + + // Returns a vector of which members of a struct are potentially in use by a + // SPIR-V shader. The granularity of this analysis is per-member of a struct. + // This can be used for Buffer (UBO), BufferBlock/StorageBuffer (SSBO) and PushConstant blocks. + // ID is the Resource::id obtained from get_shader_resources(). + SmallVector get_active_buffer_ranges(VariableID id) const; + + // Returns the effective size of a buffer block. + size_t get_declared_struct_size(const SPIRType &struct_type) const; + + // Returns the effective size of a buffer block, with a given array size + // for a runtime array. + // SSBOs are typically declared as runtime arrays. get_declared_struct_size() will return 0 for the size. + // This is not very helpful for applications which might need to know the array stride of its last member. + // This can be done through the API, but it is not very intuitive how to accomplish this, so here we provide a helper function + // to query the size of the buffer, assuming that the last member has a certain size. + // If the buffer does not contain a runtime array, array_size is ignored, and the function will behave as + // get_declared_struct_size(). + // To get the array stride of the last member, something like: + // get_declared_struct_size_runtime_array(type, 1) - get_declared_struct_size_runtime_array(type, 0) will work. + size_t get_declared_struct_size_runtime_array(const SPIRType &struct_type, size_t array_size) const; + + // Returns the effective size of a buffer block struct member. + size_t get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const; + + // Returns a set of all global variables which are statically accessed + // by the control flow graph from the current entry point. + // Only variables which change the interface for a shader are returned, that is, + // variables with storage class of Input, Output, Uniform, UniformConstant, PushConstant and AtomicCounter + // storage classes are returned. + // + // To use the returned set as the filter for which variables are used during compilation, + // this set can be moved to set_enabled_interface_variables(). + std::unordered_set get_active_interface_variables() const; + + // Sets the interface variables which are used during compilation. + // By default, all variables are used. + // Once set, compile() will only consider the set in active_variables. + void set_enabled_interface_variables(std::unordered_set active_variables); + + // Query shader resources, use ids with reflection interface to modify or query binding points, etc. + ShaderResources get_shader_resources() const; + + // Query shader resources, but only return the variables which are part of active_variables. + // E.g.: get_shader_resources(get_active_variables()) to only return the variables which are statically + // accessed. + ShaderResources get_shader_resources(const std::unordered_set &active_variables) const; + + // Remapped variables are considered built-in variables and a backend will + // not emit a declaration for this variable. + // This is mostly useful for making use of builtins which are dependent on extensions. + void set_remapped_variable_state(VariableID id, bool remap_enable); + bool get_remapped_variable_state(VariableID id) const; + + // For subpassInput variables which are remapped to plain variables, + // the number of components in the remapped + // variable must be specified as the backing type of subpass inputs are opaque. + void set_subpass_input_remapped_components(VariableID id, uint32_t components); + uint32_t get_subpass_input_remapped_components(VariableID id) const; + + // All operations work on the current entry point. + // Entry points can be swapped out with set_entry_point(). + // Entry points should be set right after the constructor completes as some reflection functions traverse the graph from the entry point. + // Resource reflection also depends on the entry point. + // By default, the current entry point is set to the first OpEntryPoint which appears in the SPIR-V module. + + // Some shader languages restrict the names that can be given to entry points, and the + // corresponding backend will automatically rename an entry point name, during the call + // to compile() if it is illegal. For example, the common entry point name main() is + // illegal in MSL, and is renamed to an alternate name by the MSL backend. + // Given the original entry point name contained in the SPIR-V, this function returns + // the name, as updated by the backend during the call to compile(). If the name is not + // illegal, and has not been renamed, or if this function is called before compile(), + // this function will simply return the same name. + + // New variants of entry point query and reflection. + // Names for entry points in the SPIR-V module may alias if they belong to different execution models. + // To disambiguate, we must pass along with the entry point names the execution model. + SmallVector get_entry_points_and_stages() const; + void set_entry_point(const std::string &entry, spv::ExecutionModel execution_model); + + // Renames an entry point from old_name to new_name. + // If old_name is currently selected as the current entry point, it will continue to be the current entry point, + // albeit with a new name. + // get_entry_points() is essentially invalidated at this point. + void rename_entry_point(const std::string &old_name, const std::string &new_name, + spv::ExecutionModel execution_model); + const SPIREntryPoint &get_entry_point(const std::string &name, spv::ExecutionModel execution_model) const; + SPIREntryPoint &get_entry_point(const std::string &name, spv::ExecutionModel execution_model); + const std::string &get_cleansed_entry_point_name(const std::string &name, + spv::ExecutionModel execution_model) const; + + // Traverses all reachable opcodes and sets active_builtins to a bitmask of all builtin variables which are accessed in the shader. + void update_active_builtins(); + bool has_active_builtin(spv::BuiltIn builtin, spv::StorageClass storage); + + // Query and modify OpExecutionMode. + const Bitset &get_execution_mode_bitset() const; + + void unset_execution_mode(spv::ExecutionMode mode); + void set_execution_mode(spv::ExecutionMode mode, uint32_t arg0 = 0, uint32_t arg1 = 0, uint32_t arg2 = 0); + + // Gets argument for an execution mode (LocalSize, Invocations, OutputVertices). + // For LocalSize, the index argument is used to select the dimension (X = 0, Y = 1, Z = 2). + // For execution modes which do not have arguments, 0 is returned. + uint32_t get_execution_mode_argument(spv::ExecutionMode mode, uint32_t index = 0) const; + spv::ExecutionModel get_execution_model() const; + + bool is_tessellation_shader() const; + + // In SPIR-V, the compute work group size can be represented by a constant vector, in which case + // the LocalSize execution mode is ignored. + // + // This constant vector can be a constant vector, specialization constant vector, or partly specialized constant vector. + // To modify and query work group dimensions which are specialization constants, SPIRConstant values must be modified + // directly via get_constant() rather than using LocalSize directly. This function will return which constants should be modified. + // + // To modify dimensions which are *not* specialization constants, set_execution_mode should be used directly. + // Arguments to set_execution_mode which are specialization constants are effectively ignored during compilation. + // NOTE: This is somewhat different from how SPIR-V works. In SPIR-V, the constant vector will completely replace LocalSize, + // while in this interface, LocalSize is only ignored for specialization constants. + // + // The specialization constant will be written to x, y and z arguments. + // If the component is not a specialization constant, a zeroed out struct will be written. + // The return value is the constant ID of the builtin WorkGroupSize, but this is not expected to be useful + // for most use cases. + uint32_t get_work_group_size_specialization_constants(SpecializationConstant &x, SpecializationConstant &y, + SpecializationConstant &z) const; + + // Analyzes all OpImageFetch (texelFetch) opcodes and checks if there are instances where + // said instruction is used without a combined image sampler. + // GLSL targets do not support the use of texelFetch without a sampler. + // To workaround this, we must inject a dummy sampler which can be used to form a sampler2D at the call-site of + // texelFetch as necessary. + // + // This must be called before build_combined_image_samplers(). + // build_combined_image_samplers() may refer to the ID returned by this method if the returned ID is non-zero. + // The return value will be the ID of a sampler object if a dummy sampler is necessary, or 0 if no sampler object + // is required. + // + // If the returned ID is non-zero, it can be decorated with set/bindings as desired before calling compile(). + // Calling this function also invalidates get_active_interface_variables(), so this should be called + // before that function. + VariableID build_dummy_sampler_for_combined_images(); + + // Analyzes all separate image and samplers used from the currently selected entry point, + // and re-routes them all to a combined image sampler instead. + // This is required to "support" separate image samplers in targets which do not natively support + // this feature, like GLSL/ESSL. + // + // This must be called before compile() if such remapping is desired. + // This call will add new sampled images to the SPIR-V, + // so it will appear in reflection if get_shader_resources() is called after build_combined_image_samplers. + // + // If any image/sampler remapping was found, no separate image/samplers will appear in the decompiled output, + // but will still appear in reflection. + // + // The resulting samplers will be void of any decorations like name, descriptor sets and binding points, + // so this can be added before compile() if desired. + // + // Combined image samplers originating from this set are always considered active variables. + // Arrays of separate samplers are not supported, but arrays of separate images are supported. + // Array of images + sampler -> Array of combined image samplers. + void build_combined_image_samplers(); + + // Gets a remapping for the combined image samplers. + const SmallVector &get_combined_image_samplers() const + { + return combined_image_samplers; + } + + // Set a new variable type remap callback. + // The type remapping is designed to allow global interface variable to assume more special types. + // A typical example here is to remap sampler2D into samplerExternalOES, which currently isn't supported + // directly by SPIR-V. + // + // In compile() while emitting code, + // for every variable that is declared, including function parameters, the callback will be called + // and the API user has a chance to change the textual representation of the type used to declare the variable. + // The API user can detect special patterns in names to guide the remapping. + void set_variable_type_remap_callback(VariableTypeRemapCallback cb) + { + variable_remap_callback = std::move(cb); + } + + // API for querying which specialization constants exist. + // To modify a specialization constant before compile(), use get_constant(constant.id), + // then update constants directly in the SPIRConstant data structure. + // For composite types, the subconstants can be iterated over and modified. + // constant_type is the SPIRType for the specialization constant, + // which can be queried to determine which fields in the unions should be poked at. + SmallVector get_specialization_constants() const; + SPIRConstant &get_constant(ConstantID id); + const SPIRConstant &get_constant(ConstantID id) const; + + uint32_t get_current_id_bound() const + { + return uint32_t(ir.ids.size()); + } + + // API for querying buffer objects. + // The type passed in here should be the base type of a resource, i.e. + // get_type(resource.base_type_id) + // as decorations are set in the basic Block type. + // The type passed in here must have these decorations set, or an exception is raised. + // Only UBOs and SSBOs or sub-structs which are part of these buffer types will have these decorations set. + uint32_t type_struct_member_offset(const SPIRType &type, uint32_t index) const; + uint32_t type_struct_member_array_stride(const SPIRType &type, uint32_t index) const; + uint32_t type_struct_member_matrix_stride(const SPIRType &type, uint32_t index) const; + + // Gets the offset in SPIR-V words (uint32_t) for a decoration which was originally declared in the SPIR-V binary. + // The offset will point to one or more uint32_t literals which can be modified in-place before using the SPIR-V binary. + // Note that adding or removing decorations using the reflection API will not change the behavior of this function. + // If the decoration was declared, sets the word_offset to an offset into the provided SPIR-V binary buffer and returns true, + // otherwise, returns false. + // If the decoration does not have any value attached to it (e.g. DecorationRelaxedPrecision), this function will also return false. + bool get_binary_offset_for_decoration(VariableID id, spv::Decoration decoration, uint32_t &word_offset) const; + + // HLSL counter buffer reflection interface. + // Append/Consume/Increment/Decrement in HLSL is implemented as two "neighbor" buffer objects where + // one buffer implements the storage, and a single buffer containing just a lone "int" implements the counter. + // To SPIR-V these will be exposed as two separate buffers, but glslang HLSL frontend emits a special indentifier + // which lets us link the two buffers together. + + // Queries if a variable ID is a counter buffer which "belongs" to a regular buffer object. + + // If SPV_GOOGLE_hlsl_functionality1 is used, this can be used even with a stripped SPIR-V module. + // Otherwise, this query is purely based on OpName identifiers as found in the SPIR-V module, and will + // only return true if OpSource was reported HLSL. + // To rely on this functionality, ensure that the SPIR-V module is not stripped. + + bool buffer_is_hlsl_counter_buffer(VariableID id) const; + + // Queries if a buffer object has a neighbor "counter" buffer. + // If so, the ID of that counter buffer will be returned in counter_id. + // If SPV_GOOGLE_hlsl_functionality1 is used, this can be used even with a stripped SPIR-V module. + // Otherwise, this query is purely based on OpName identifiers as found in the SPIR-V module, and will + // only return true if OpSource was reported HLSL. + // To rely on this functionality, ensure that the SPIR-V module is not stripped. + bool buffer_get_hlsl_counter_buffer(VariableID id, uint32_t &counter_id) const; + + // Gets the list of all SPIR-V Capabilities which were declared in the SPIR-V module. + const SmallVector &get_declared_capabilities() const; + + // Gets the list of all SPIR-V extensions which were declared in the SPIR-V module. + const SmallVector &get_declared_extensions() const; + + // When declaring buffer blocks in GLSL, the name declared in the GLSL source + // might not be the same as the name declared in the SPIR-V module due to naming conflicts. + // In this case, SPIRV-Cross needs to find a fallback-name, and it might only + // be possible to know this name after compiling to GLSL. + // This is particularly important for HLSL input and UAVs which tends to reuse the same block type + // for multiple distinct blocks. For these cases it is not possible to modify the name of the type itself + // because it might be unique. Instead, you can use this interface to check after compilation which + // name was actually used if your input SPIR-V tends to have this problem. + // For other names like remapped names for variables, etc, it's generally enough to query the name of the variables + // after compiling, block names are an exception to this rule. + // ID is the name of a variable as returned by Resource::id, and must be a variable with a Block-like type. + // + // This also applies to HLSL cbuffers. + std::string get_remapped_declared_block_name(VariableID id) const; + + // For buffer block variables, get the decorations for that variable. + // Sometimes, decorations for buffer blocks are found in member decorations instead + // of direct decorations on the variable itself. + // The most common use here is to check if a buffer is readonly or writeonly. + Bitset get_buffer_block_flags(VariableID id) const; + +protected: + const uint32_t *stream(const Instruction &instr) const + { + // If we're not going to use any arguments, just return nullptr. + // We want to avoid case where we return an out of range pointer + // that trips debug assertions on some platforms. + if (!instr.length) + return nullptr; + + if (instr.offset + instr.length > ir.spirv.size()) + SPIRV_CROSS_THROW("Compiler::stream() out of range."); + return &ir.spirv[instr.offset]; + } + + ParsedIR ir; + // Marks variables which have global scope and variables which can alias with other variables + // (SSBO, image load store, etc) + SmallVector global_variables; + SmallVector aliased_variables; + + SPIRFunction *current_function = nullptr; + SPIRBlock *current_block = nullptr; + std::unordered_set active_interface_variables; + bool check_active_interface_variables = false; + + // If our IDs are out of range here as part of opcodes, throw instead of + // undefined behavior. + template + T &set(uint32_t id, P &&... args) + { + ir.add_typed_id(static_cast(T::type), id); + auto &var = variant_set(ir.ids[id], std::forward

(args)...); + var.self = id; + return var; + } + + template + T &get(uint32_t id) + { + return variant_get(ir.ids[id]); + } + + template + T *maybe_get(uint32_t id) + { + if (id >= ir.ids.size()) + return nullptr; + else if (ir.ids[id].get_type() == static_cast(T::type)) + return &get(id); + else + return nullptr; + } + + template + const T &get(uint32_t id) const + { + return variant_get(ir.ids[id]); + } + + template + const T *maybe_get(uint32_t id) const + { + if (id >= ir.ids.size()) + return nullptr; + else if (ir.ids[id].get_type() == static_cast(T::type)) + return &get(id); + else + return nullptr; + } + + // Gets the id of SPIR-V type underlying the given type_id, which might be a pointer. + uint32_t get_pointee_type_id(uint32_t type_id) const; + + // Gets the SPIR-V type underlying the given type, which might be a pointer. + const SPIRType &get_pointee_type(const SPIRType &type) const; + + // Gets the SPIR-V type underlying the given type_id, which might be a pointer. + const SPIRType &get_pointee_type(uint32_t type_id) const; + + // Gets the ID of the SPIR-V type underlying a variable. + uint32_t get_variable_data_type_id(const SPIRVariable &var) const; + + // Gets the SPIR-V type underlying a variable. + SPIRType &get_variable_data_type(const SPIRVariable &var); + + // Gets the SPIR-V type underlying a variable. + const SPIRType &get_variable_data_type(const SPIRVariable &var) const; + + // Gets the SPIR-V element type underlying an array variable. + SPIRType &get_variable_element_type(const SPIRVariable &var); + + // Gets the SPIR-V element type underlying an array variable. + const SPIRType &get_variable_element_type(const SPIRVariable &var) const; + + // Sets the qualified member identifier for OpTypeStruct ID, member number "index". + void set_member_qualified_name(uint32_t type_id, uint32_t index, const std::string &name); + void set_qualified_name(uint32_t id, const std::string &name); + + // Returns if the given type refers to a sampled image. + bool is_sampled_image_type(const SPIRType &type); + + const SPIREntryPoint &get_entry_point() const; + SPIREntryPoint &get_entry_point(); + static bool is_tessellation_shader(spv::ExecutionModel model); + + virtual std::string to_name(uint32_t id, bool allow_alias = true) const; + bool is_builtin_variable(const SPIRVariable &var) const; + bool is_builtin_type(const SPIRType &type) const; + bool is_hidden_variable(const SPIRVariable &var, bool include_builtins = false) const; + bool is_immutable(uint32_t id) const; + bool is_member_builtin(const SPIRType &type, uint32_t index, spv::BuiltIn *builtin) const; + bool is_scalar(const SPIRType &type) const; + bool is_vector(const SPIRType &type) const; + bool is_matrix(const SPIRType &type) const; + bool is_array(const SPIRType &type) const; + uint32_t expression_type_id(uint32_t id) const; + const SPIRType &expression_type(uint32_t id) const; + bool expression_is_lvalue(uint32_t id) const; + bool variable_storage_is_aliased(const SPIRVariable &var); + SPIRVariable *maybe_get_backing_variable(uint32_t chain); + spv::StorageClass get_backing_variable_storage(uint32_t ptr); + + void register_read(uint32_t expr, uint32_t chain, bool forwarded); + void register_write(uint32_t chain); + + inline bool is_continue(uint32_t next) const + { + return (ir.block_meta[next] & ParsedIR::BLOCK_META_CONTINUE_BIT) != 0; + } + + inline bool is_single_block_loop(uint32_t next) const + { + auto &block = get(next); + return block.merge == SPIRBlock::MergeLoop && block.continue_block == ID(next); + } + + inline bool is_break(uint32_t next) const + { + return (ir.block_meta[next] & + (ParsedIR::BLOCK_META_LOOP_MERGE_BIT | ParsedIR::BLOCK_META_MULTISELECT_MERGE_BIT)) != 0; + } + + inline bool is_loop_break(uint32_t next) const + { + return (ir.block_meta[next] & ParsedIR::BLOCK_META_LOOP_MERGE_BIT) != 0; + } + + inline bool is_conditional(uint32_t next) const + { + return (ir.block_meta[next] & + (ParsedIR::BLOCK_META_SELECTION_MERGE_BIT | ParsedIR::BLOCK_META_MULTISELECT_MERGE_BIT)) != 0; + } + + // Dependency tracking for temporaries read from variables. + void flush_dependees(SPIRVariable &var); + void flush_all_active_variables(); + void flush_control_dependent_expressions(uint32_t block); + void flush_all_atomic_capable_variables(); + void flush_all_aliased_variables(); + void register_global_read_dependencies(const SPIRBlock &func, uint32_t id); + void register_global_read_dependencies(const SPIRFunction &func, uint32_t id); + std::unordered_set invalid_expressions; + + void update_name_cache(std::unordered_set &cache, std::string &name); + + // A variant which takes two sets of names. The secondary is only used to verify there are no collisions, + // but the set is not updated when we have found a new name. + // Used primarily when adding block interface names. + void update_name_cache(std::unordered_set &cache_primary, + const std::unordered_set &cache_secondary, std::string &name); + + bool function_is_pure(const SPIRFunction &func); + bool block_is_pure(const SPIRBlock &block); + + bool execution_is_branchless(const SPIRBlock &from, const SPIRBlock &to) const; + bool execution_is_direct_branch(const SPIRBlock &from, const SPIRBlock &to) const; + bool execution_is_noop(const SPIRBlock &from, const SPIRBlock &to) const; + SPIRBlock::ContinueBlockType continue_block_type(const SPIRBlock &continue_block) const; + + void force_recompile(); + void clear_force_recompile(); + bool is_forcing_recompilation() const; + bool is_force_recompile = false; + + bool block_is_loop_candidate(const SPIRBlock &block, SPIRBlock::Method method) const; + + bool types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const; + void inherit_expression_dependencies(uint32_t dst, uint32_t source); + void add_implied_read_expression(SPIRExpression &e, uint32_t source); + void add_implied_read_expression(SPIRAccessChain &e, uint32_t source); + + // For proper multiple entry point support, allow querying if an Input or Output + // variable is part of that entry points interface. + bool interface_variable_exists_in_entry_point(uint32_t id) const; + + SmallVector combined_image_samplers; + + void remap_variable_type_name(const SPIRType &type, const std::string &var_name, std::string &type_name) const + { + if (variable_remap_callback) + variable_remap_callback(type, var_name, type_name); + } + + void set_ir(const ParsedIR &parsed); + void set_ir(ParsedIR &&parsed); + void parse_fixup(); + + // Used internally to implement various traversals for queries. + struct OpcodeHandler + { + virtual ~OpcodeHandler() = default; + + // Return true if traversal should continue. + // If false, traversal will end immediately. + virtual bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) = 0; + + virtual bool follow_function_call(const SPIRFunction &) + { + return true; + } + + virtual void set_current_block(const SPIRBlock &) + { + } + + // Called after returning from a function or when entering a block, + // can be called multiple times per block, + // while set_current_block is only called on block entry. + virtual void rearm_current_block(const SPIRBlock &) + { + } + + virtual bool begin_function_scope(const uint32_t *, uint32_t) + { + return true; + } + + virtual bool end_function_scope(const uint32_t *, uint32_t) + { + return true; + } + }; + + struct BufferAccessHandler : OpcodeHandler + { + BufferAccessHandler(const Compiler &compiler_, SmallVector &ranges_, uint32_t id_) + : compiler(compiler_) + , ranges(ranges_) + , id(id_) + { + } + + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + + const Compiler &compiler; + SmallVector &ranges; + uint32_t id; + + std::unordered_set seen; + }; + + struct InterfaceVariableAccessHandler : OpcodeHandler + { + InterfaceVariableAccessHandler(const Compiler &compiler_, std::unordered_set &variables_) + : compiler(compiler_) + , variables(variables_) + { + } + + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + + const Compiler &compiler; + std::unordered_set &variables; + }; + + struct CombinedImageSamplerHandler : OpcodeHandler + { + CombinedImageSamplerHandler(Compiler &compiler_) + : compiler(compiler_) + { + } + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + bool begin_function_scope(const uint32_t *args, uint32_t length) override; + bool end_function_scope(const uint32_t *args, uint32_t length) override; + + Compiler &compiler; + + // Each function in the call stack needs its own remapping for parameters so we can deduce which global variable each texture/sampler the parameter is statically bound to. + std::stack> parameter_remapping; + std::stack functions; + + uint32_t remap_parameter(uint32_t id); + void push_remap_parameters(const SPIRFunction &func, const uint32_t *args, uint32_t length); + void pop_remap_parameters(); + void register_combined_image_sampler(SPIRFunction &caller, VariableID combined_id, VariableID texture_id, + VariableID sampler_id, bool depth); + }; + + struct DummySamplerForCombinedImageHandler : OpcodeHandler + { + DummySamplerForCombinedImageHandler(Compiler &compiler_) + : compiler(compiler_) + { + } + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + + Compiler &compiler; + bool need_dummy_sampler = false; + }; + + struct ActiveBuiltinHandler : OpcodeHandler + { + ActiveBuiltinHandler(Compiler &compiler_) + : compiler(compiler_) + { + } + + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + Compiler &compiler; + + void handle_builtin(const SPIRType &type, spv::BuiltIn builtin, const Bitset &decoration_flags); + }; + + bool traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const; + bool traverse_all_reachable_opcodes(const SPIRFunction &block, OpcodeHandler &handler) const; + // This must be an ordered data structure so we always pick the same type aliases. + SmallVector global_struct_cache; + + ShaderResources get_shader_resources(const std::unordered_set *active_variables) const; + + VariableTypeRemapCallback variable_remap_callback; + + bool get_common_basic_type(const SPIRType &type, SPIRType::BaseType &base_type); + + std::unordered_set forced_temporaries; + std::unordered_set forwarded_temporaries; + std::unordered_set suppressed_usage_tracking; + std::unordered_set hoisted_temporaries; + std::unordered_set forced_invariant_temporaries; + + Bitset active_input_builtins; + Bitset active_output_builtins; + uint32_t clip_distance_count = 0; + uint32_t cull_distance_count = 0; + bool position_invariant = false; + + void analyze_parameter_preservation( + SPIRFunction &entry, const CFG &cfg, + const std::unordered_map> &variable_to_blocks, + const std::unordered_map> &complete_write_blocks); + + // If a variable ID or parameter ID is found in this set, a sampler is actually a shadow/comparison sampler. + // SPIR-V does not support this distinction, so we must keep track of this information outside the type system. + // There might be unrelated IDs found in this set which do not correspond to actual variables. + // This set should only be queried for the existence of samplers which are already known to be variables or parameter IDs. + // Similar is implemented for images, as well as if subpass inputs are needed. + std::unordered_set comparison_ids; + bool need_subpass_input = false; + + // In certain backends, we will need to use a dummy sampler to be able to emit code. + // GLSL does not support texelFetch on texture2D objects, but SPIR-V does, + // so we need to workaround by having the application inject a dummy sampler. + uint32_t dummy_sampler_id = 0; + + void analyze_image_and_sampler_usage(); + + struct CombinedImageSamplerDrefHandler : OpcodeHandler + { + CombinedImageSamplerDrefHandler(Compiler &compiler_) + : compiler(compiler_) + { + } + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + + Compiler &compiler; + std::unordered_set dref_combined_samplers; + }; + + struct CombinedImageSamplerUsageHandler : OpcodeHandler + { + CombinedImageSamplerUsageHandler(Compiler &compiler_, + const std::unordered_set &dref_combined_samplers_) + : compiler(compiler_) + , dref_combined_samplers(dref_combined_samplers_) + { + } + + bool begin_function_scope(const uint32_t *args, uint32_t length) override; + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + Compiler &compiler; + const std::unordered_set &dref_combined_samplers; + + std::unordered_map> dependency_hierarchy; + std::unordered_set comparison_ids; + + void add_hierarchy_to_comparison_ids(uint32_t ids); + bool need_subpass_input = false; + void add_dependency(uint32_t dst, uint32_t src); + }; + + void build_function_control_flow_graphs_and_analyze(); + std::unordered_map> function_cfgs; + const CFG &get_cfg_for_current_function() const; + const CFG &get_cfg_for_function(uint32_t id) const; + + struct CFGBuilder : OpcodeHandler + { + explicit CFGBuilder(Compiler &compiler_); + + bool follow_function_call(const SPIRFunction &func) override; + bool handle(spv::Op op, const uint32_t *args, uint32_t length) override; + Compiler &compiler; + std::unordered_map> function_cfgs; + }; + + struct AnalyzeVariableScopeAccessHandler : OpcodeHandler + { + AnalyzeVariableScopeAccessHandler(Compiler &compiler_, SPIRFunction &entry_); + + bool follow_function_call(const SPIRFunction &) override; + void set_current_block(const SPIRBlock &block) override; + + void notify_variable_access(uint32_t id, uint32_t block); + bool id_is_phi_variable(uint32_t id) const; + bool id_is_potential_temporary(uint32_t id) const; + bool handle(spv::Op op, const uint32_t *args, uint32_t length) override; + + Compiler &compiler; + SPIRFunction &entry; + std::unordered_map> accessed_variables_to_block; + std::unordered_map> accessed_temporaries_to_block; + std::unordered_map result_id_to_type; + std::unordered_map> complete_write_variables_to_block; + std::unordered_map> partial_write_variables_to_block; + std::unordered_set access_chain_expressions; + // Access chains used in multiple blocks mean hoisting all the variables used to construct the access chain as not all backends can use pointers. + std::unordered_map> access_chain_children; + const SPIRBlock *current_block = nullptr; + }; + + struct StaticExpressionAccessHandler : OpcodeHandler + { + StaticExpressionAccessHandler(Compiler &compiler_, uint32_t variable_id_); + bool follow_function_call(const SPIRFunction &) override; + bool handle(spv::Op op, const uint32_t *args, uint32_t length) override; + + Compiler &compiler; + uint32_t variable_id; + uint32_t static_expression = 0; + uint32_t write_count = 0; + }; + + struct PhysicalStorageBufferPointerHandler : OpcodeHandler + { + explicit PhysicalStorageBufferPointerHandler(Compiler &compiler_); + bool handle(spv::Op op, const uint32_t *args, uint32_t length) override; + Compiler &compiler; + std::unordered_set types; + }; + void analyze_non_block_pointer_types(); + SmallVector physical_storage_non_block_pointer_types; + + void analyze_variable_scope(SPIRFunction &function, AnalyzeVariableScopeAccessHandler &handler); + void find_function_local_luts(SPIRFunction &function, const AnalyzeVariableScopeAccessHandler &handler, + bool single_function); + bool may_read_undefined_variable_in_block(const SPIRBlock &block, uint32_t var); + + // Finds all resources that are written to from inside the critical section, if present. + // The critical section is delimited by OpBeginInvocationInterlockEXT and + // OpEndInvocationInterlockEXT instructions. In MSL and HLSL, any resources written + // while inside the critical section must be placed in a raster order group. + struct InterlockedResourceAccessHandler : OpcodeHandler + { + InterlockedResourceAccessHandler(Compiler &compiler_, uint32_t entry_point_id) + : compiler(compiler_) + { + call_stack.push_back(entry_point_id); + } + + bool handle(spv::Op op, const uint32_t *args, uint32_t length) override; + bool begin_function_scope(const uint32_t *args, uint32_t length) override; + bool end_function_scope(const uint32_t *args, uint32_t length) override; + + Compiler &compiler; + bool in_crit_sec = false; + + uint32_t interlock_function_id = 0; + bool split_function_case = false; + bool control_flow_interlock = false; + bool use_critical_section = false; + bool call_stack_is_interlocked = false; + SmallVector call_stack; + + void access_potential_resource(uint32_t id); + }; + + struct InterlockedResourceAccessPrepassHandler : OpcodeHandler + { + InterlockedResourceAccessPrepassHandler(Compiler &compiler_, uint32_t entry_point_id) + : compiler(compiler_) + { + call_stack.push_back(entry_point_id); + } + + void rearm_current_block(const SPIRBlock &block) override; + bool handle(spv::Op op, const uint32_t *args, uint32_t length) override; + bool begin_function_scope(const uint32_t *args, uint32_t length) override; + bool end_function_scope(const uint32_t *args, uint32_t length) override; + + Compiler &compiler; + uint32_t interlock_function_id = 0; + uint32_t current_block_id = 0; + bool split_function_case = false; + bool control_flow_interlock = false; + SmallVector call_stack; + }; + + void analyze_interlocked_resource_usage(); + // The set of all resources written while inside the critical section, if present. + std::unordered_set interlocked_resources; + bool interlocked_is_complex = false; + + void make_constant_null(uint32_t id, uint32_t type); + + std::unordered_map declared_block_names; + + bool instruction_to_result_type(uint32_t &result_type, uint32_t &result_id, spv::Op op, const uint32_t *args, + uint32_t length); + + Bitset combined_decoration_for_member(const SPIRType &type, uint32_t index) const; + static bool is_desktop_only_format(spv::ImageFormat format); + + bool image_is_comparison(const SPIRType &type, uint32_t id) const; + + void set_extended_decoration(uint32_t id, ExtendedDecorations decoration, uint32_t value = 0); + uint32_t get_extended_decoration(uint32_t id, ExtendedDecorations decoration) const; + bool has_extended_decoration(uint32_t id, ExtendedDecorations decoration) const; + void unset_extended_decoration(uint32_t id, ExtendedDecorations decoration); + + void set_extended_member_decoration(uint32_t type, uint32_t index, ExtendedDecorations decoration, + uint32_t value = 0); + uint32_t get_extended_member_decoration(uint32_t type, uint32_t index, ExtendedDecorations decoration) const; + bool has_extended_member_decoration(uint32_t type, uint32_t index, ExtendedDecorations decoration) const; + void unset_extended_member_decoration(uint32_t type, uint32_t index, ExtendedDecorations decoration); + + bool type_is_array_of_pointers(const SPIRType &type) const; + bool type_is_block_like(const SPIRType &type) const; + bool type_is_opaque_value(const SPIRType &type) const; + + bool reflection_ssbo_instance_name_is_significant() const; + std::string get_remapped_declared_block_name(uint32_t id, bool fallback_prefer_instance_name) const; + + bool flush_phi_required(BlockID from, BlockID to) const; + +private: + // Used only to implement the old deprecated get_entry_point() interface. + const SPIREntryPoint &get_first_entry_point(const std::string &name) const; + SPIREntryPoint &get_first_entry_point(const std::string &name); +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_cross_c.h b/ios/include/spirv_cross/spirv_cross_c.h new file mode 100644 index 00000000..0c218396 --- /dev/null +++ b/ios/include/spirv_cross/spirv_cross_c.h @@ -0,0 +1,912 @@ +/* + * Copyright 2019-2020 Hans-Kristian Arntzen + * + * 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 SPIRV_CROSS_C_API_H +#define SPIRV_CROSS_C_API_H + +#include +#include "spirv.h" + +/* + * C89-compatible wrapper for SPIRV-Cross' API. + * Documentation here is sparse unless the behavior does not map 1:1 with C++ API. + * It is recommended to look at the canonical C++ API for more detailed information. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Bumped if ABI or API breaks backwards compatibility. */ +#define SPVC_C_API_VERSION_MAJOR 0 +/* Bumped if APIs or enumerations are added in a backwards compatible way. */ +#define SPVC_C_API_VERSION_MINOR 33 +/* Bumped if internal implementation details change. */ +#define SPVC_C_API_VERSION_PATCH 0 + +#if !defined(SPVC_PUBLIC_API) +#if defined(SPVC_EXPORT_SYMBOLS) +/* Exports symbols. Standard C calling convention is used. */ +#if defined(__GNUC__) +#define SPVC_PUBLIC_API __attribute__((visibility("default"))) +#elif defined(_MSC_VER) +#define SPVC_PUBLIC_API __declspec(dllexport) +#else +#define SPVC_PUBLIC_API +#endif +#else +#define SPVC_PUBLIC_API +#endif +#endif + +/* + * Gets the SPVC_C_API_VERSION_* used to build this library. + * Can be used to check for ABI mismatch if so-versioning did not catch it. + */ +SPVC_PUBLIC_API void spvc_get_version(unsigned *major, unsigned *minor, unsigned *patch); + +/* Gets a human readable version string to identify which commit a particular binary was created from. */ +SPVC_PUBLIC_API const char *spvc_get_commit_revision_and_timestamp(void); + +/* These types are opaque to the user. */ +typedef struct spvc_context_s *spvc_context; +typedef struct spvc_parsed_ir_s *spvc_parsed_ir; +typedef struct spvc_compiler_s *spvc_compiler; +typedef struct spvc_compiler_options_s *spvc_compiler_options; +typedef struct spvc_resources_s *spvc_resources; +struct spvc_type_s; +typedef const struct spvc_type_s *spvc_type; +typedef struct spvc_constant_s *spvc_constant; +struct spvc_set_s; +typedef const struct spvc_set_s *spvc_set; + +/* + * Shallow typedefs. All SPIR-V IDs are plain 32-bit numbers, but this helps communicate which data is used. + * Maps to a SPIRType. + */ +typedef SpvId spvc_type_id; +/* Maps to a SPIRVariable. */ +typedef SpvId spvc_variable_id; +/* Maps to a SPIRConstant. */ +typedef SpvId spvc_constant_id; + +/* See C++ API. */ +typedef struct spvc_reflected_resource +{ + spvc_variable_id id; + spvc_type_id base_type_id; + spvc_type_id type_id; + const char *name; +} spvc_reflected_resource; + +/* See C++ API. */ +typedef struct spvc_entry_point +{ + SpvExecutionModel execution_model; + const char *name; +} spvc_entry_point; + +/* See C++ API. */ +typedef struct spvc_combined_image_sampler +{ + spvc_variable_id combined_id; + spvc_variable_id image_id; + spvc_variable_id sampler_id; +} spvc_combined_image_sampler; + +/* See C++ API. */ +typedef struct spvc_specialization_constant +{ + spvc_constant_id id; + unsigned constant_id; +} spvc_specialization_constant; + +/* See C++ API. */ +typedef struct spvc_buffer_range +{ + unsigned index; + size_t offset; + size_t range; +} spvc_buffer_range; + +/* See C++ API. */ +typedef struct spvc_hlsl_root_constants +{ + unsigned start; + unsigned end; + unsigned binding; + unsigned space; +} spvc_hlsl_root_constants; + +/* See C++ API. */ +typedef struct spvc_hlsl_vertex_attribute_remap +{ + unsigned location; + const char *semantic; +} spvc_hlsl_vertex_attribute_remap; + +/* + * Be compatible with non-C99 compilers, which do not have stdbool. + * Only recent MSVC compilers supports this for example, and ideally SPIRV-Cross should be linkable + * from a wide range of compilers in its C wrapper. + */ +typedef unsigned char spvc_bool; +#define SPVC_TRUE ((spvc_bool)1) +#define SPVC_FALSE ((spvc_bool)0) + +typedef enum spvc_result +{ + /* Success. */ + SPVC_SUCCESS = 0, + + /* The SPIR-V is invalid. Should have been caught by validation ideally. */ + SPVC_ERROR_INVALID_SPIRV = -1, + + /* The SPIR-V might be valid or invalid, but SPIRV-Cross currently cannot correctly translate this to your target language. */ + SPVC_ERROR_UNSUPPORTED_SPIRV = -2, + + /* If for some reason we hit this, new or malloc failed. */ + SPVC_ERROR_OUT_OF_MEMORY = -3, + + /* Invalid API argument. */ + SPVC_ERROR_INVALID_ARGUMENT = -4, + + SPVC_ERROR_INT_MAX = 0x7fffffff +} spvc_result; + +typedef enum spvc_capture_mode +{ + /* The Parsed IR payload will be copied, and the handle can be reused to create other compiler instances. */ + SPVC_CAPTURE_MODE_COPY = 0, + + /* + * The payload will now be owned by the compiler. + * parsed_ir should now be considered a dead blob and must not be used further. + * This is optimal for performance and should be the go-to option. + */ + SPVC_CAPTURE_MODE_TAKE_OWNERSHIP = 1, + + SPVC_CAPTURE_MODE_INT_MAX = 0x7fffffff +} spvc_capture_mode; + +typedef enum spvc_backend +{ + /* This backend can only perform reflection, no compiler options are supported. Maps to spirv_cross::Compiler. */ + SPVC_BACKEND_NONE = 0, + SPVC_BACKEND_GLSL = 1, /* spirv_cross::CompilerGLSL */ + SPVC_BACKEND_HLSL = 2, /* CompilerHLSL */ + SPVC_BACKEND_MSL = 3, /* CompilerMSL */ + SPVC_BACKEND_CPP = 4, /* CompilerCPP */ + SPVC_BACKEND_JSON = 5, /* CompilerReflection w/ JSON backend */ + SPVC_BACKEND_INT_MAX = 0x7fffffff +} spvc_backend; + +/* Maps to C++ API. */ +typedef enum spvc_resource_type +{ + SPVC_RESOURCE_TYPE_UNKNOWN = 0, + SPVC_RESOURCE_TYPE_UNIFORM_BUFFER = 1, + SPVC_RESOURCE_TYPE_STORAGE_BUFFER = 2, + SPVC_RESOURCE_TYPE_STAGE_INPUT = 3, + SPVC_RESOURCE_TYPE_STAGE_OUTPUT = 4, + SPVC_RESOURCE_TYPE_SUBPASS_INPUT = 5, + SPVC_RESOURCE_TYPE_STORAGE_IMAGE = 6, + SPVC_RESOURCE_TYPE_SAMPLED_IMAGE = 7, + SPVC_RESOURCE_TYPE_ATOMIC_COUNTER = 8, + SPVC_RESOURCE_TYPE_PUSH_CONSTANT = 9, + SPVC_RESOURCE_TYPE_SEPARATE_IMAGE = 10, + SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS = 11, + SPVC_RESOURCE_TYPE_ACCELERATION_STRUCTURE = 12, + SPVC_RESOURCE_TYPE_RAY_QUERY = 13, + SPVC_RESOURCE_TYPE_INT_MAX = 0x7fffffff +} spvc_resource_type; + +/* Maps to spirv_cross::SPIRType::BaseType. */ +typedef enum spvc_basetype +{ + SPVC_BASETYPE_UNKNOWN = 0, + SPVC_BASETYPE_VOID = 1, + SPVC_BASETYPE_BOOLEAN = 2, + SPVC_BASETYPE_INT8 = 3, + SPVC_BASETYPE_UINT8 = 4, + SPVC_BASETYPE_INT16 = 5, + SPVC_BASETYPE_UINT16 = 6, + SPVC_BASETYPE_INT32 = 7, + SPVC_BASETYPE_UINT32 = 8, + SPVC_BASETYPE_INT64 = 9, + SPVC_BASETYPE_UINT64 = 10, + SPVC_BASETYPE_ATOMIC_COUNTER = 11, + SPVC_BASETYPE_FP16 = 12, + SPVC_BASETYPE_FP32 = 13, + SPVC_BASETYPE_FP64 = 14, + SPVC_BASETYPE_STRUCT = 15, + SPVC_BASETYPE_IMAGE = 16, + SPVC_BASETYPE_SAMPLED_IMAGE = 17, + SPVC_BASETYPE_SAMPLER = 18, + SPVC_BASETYPE_ACCELERATION_STRUCTURE = 19, + + SPVC_BASETYPE_INT_MAX = 0x7fffffff +} spvc_basetype; + +#define SPVC_COMPILER_OPTION_COMMON_BIT 0x1000000 +#define SPVC_COMPILER_OPTION_GLSL_BIT 0x2000000 +#define SPVC_COMPILER_OPTION_HLSL_BIT 0x4000000 +#define SPVC_COMPILER_OPTION_MSL_BIT 0x8000000 +#define SPVC_COMPILER_OPTION_LANG_BITS 0x0f000000 +#define SPVC_COMPILER_OPTION_ENUM_BITS 0xffffff + +#define SPVC_MAKE_MSL_VERSION(major, minor, patch) ((major) * 10000 + (minor) * 100 + (patch)) + +/* Maps to C++ API. */ +typedef enum spvc_msl_platform +{ + SPVC_MSL_PLATFORM_IOS = 0, + SPVC_MSL_PLATFORM_MACOS = 1, + SPVC_MSL_PLATFORM_MAX_INT = 0x7fffffff +} spvc_msl_platform; + +/* Maps to C++ API. */ +typedef enum spvc_msl_vertex_format +{ + SPVC_MSL_VERTEX_FORMAT_OTHER = 0, + SPVC_MSL_VERTEX_FORMAT_UINT8 = 1, + SPVC_MSL_VERTEX_FORMAT_UINT16 = 2 +} spvc_msl_vertex_format; + +/* Maps to C++ API. */ +typedef struct spvc_msl_vertex_attribute +{ + unsigned location; + unsigned msl_buffer; + unsigned msl_offset; + unsigned msl_stride; + spvc_bool per_instance; + spvc_msl_vertex_format format; + SpvBuiltIn builtin; +} spvc_msl_vertex_attribute; + +/* + * Initializes the vertex attribute struct. + */ +SPVC_PUBLIC_API void spvc_msl_vertex_attribute_init(spvc_msl_vertex_attribute *attr); + +/* Maps to C++ API. */ +typedef struct spvc_msl_resource_binding +{ + SpvExecutionModel stage; + unsigned desc_set; + unsigned binding; + unsigned msl_buffer; + unsigned msl_texture; + unsigned msl_sampler; +} spvc_msl_resource_binding; + +/* + * Initializes the resource binding struct. + * The defaults are non-zero. + */ +SPVC_PUBLIC_API void spvc_msl_resource_binding_init(spvc_msl_resource_binding *binding); + +#define SPVC_MSL_PUSH_CONSTANT_DESC_SET (~(0u)) +#define SPVC_MSL_PUSH_CONSTANT_BINDING (0) +#define SPVC_MSL_SWIZZLE_BUFFER_BINDING (~(1u)) +#define SPVC_MSL_BUFFER_SIZE_BUFFER_BINDING (~(2u)) +#define SPVC_MSL_ARGUMENT_BUFFER_BINDING (~(3u)) + +/* Obsolete. Sticks around for backwards compatibility. */ +#define SPVC_MSL_AUX_BUFFER_STRUCT_VERSION 1 + +/* Runtime check for incompatibility. Obsolete. */ +SPVC_PUBLIC_API unsigned spvc_msl_get_aux_buffer_struct_version(void); + +/* Maps to C++ API. */ +typedef enum spvc_msl_sampler_coord +{ + SPVC_MSL_SAMPLER_COORD_NORMALIZED = 0, + SPVC_MSL_SAMPLER_COORD_PIXEL = 1, + SPVC_MSL_SAMPLER_INT_MAX = 0x7fffffff +} spvc_msl_sampler_coord; + +/* Maps to C++ API. */ +typedef enum spvc_msl_sampler_filter +{ + SPVC_MSL_SAMPLER_FILTER_NEAREST = 0, + SPVC_MSL_SAMPLER_FILTER_LINEAR = 1, + SPVC_MSL_SAMPLER_FILTER_INT_MAX = 0x7fffffff +} spvc_msl_sampler_filter; + +/* Maps to C++ API. */ +typedef enum spvc_msl_sampler_mip_filter +{ + SPVC_MSL_SAMPLER_MIP_FILTER_NONE = 0, + SPVC_MSL_SAMPLER_MIP_FILTER_NEAREST = 1, + SPVC_MSL_SAMPLER_MIP_FILTER_LINEAR = 2, + SPVC_MSL_SAMPLER_MIP_FILTER_INT_MAX = 0x7fffffff +} spvc_msl_sampler_mip_filter; + +/* Maps to C++ API. */ +typedef enum spvc_msl_sampler_address +{ + SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_ZERO = 0, + SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE = 1, + SPVC_MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER = 2, + SPVC_MSL_SAMPLER_ADDRESS_REPEAT = 3, + SPVC_MSL_SAMPLER_ADDRESS_MIRRORED_REPEAT = 4, + SPVC_MSL_SAMPLER_ADDRESS_INT_MAX = 0x7fffffff +} spvc_msl_sampler_address; + +/* Maps to C++ API. */ +typedef enum spvc_msl_sampler_compare_func +{ + SPVC_MSL_SAMPLER_COMPARE_FUNC_NEVER = 0, + SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS = 1, + SPVC_MSL_SAMPLER_COMPARE_FUNC_LESS_EQUAL = 2, + SPVC_MSL_SAMPLER_COMPARE_FUNC_GREATER = 3, + SPVC_MSL_SAMPLER_COMPARE_FUNC_GREATER_EQUAL = 4, + SPVC_MSL_SAMPLER_COMPARE_FUNC_EQUAL = 5, + SPVC_MSL_SAMPLER_COMPARE_FUNC_NOT_EQUAL = 6, + SPVC_MSL_SAMPLER_COMPARE_FUNC_ALWAYS = 7, + SPVC_MSL_SAMPLER_COMPARE_FUNC_INT_MAX = 0x7fffffff +} spvc_msl_sampler_compare_func; + +/* Maps to C++ API. */ +typedef enum spvc_msl_sampler_border_color +{ + SPVC_MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK = 0, + SPVC_MSL_SAMPLER_BORDER_COLOR_OPAQUE_BLACK = 1, + SPVC_MSL_SAMPLER_BORDER_COLOR_OPAQUE_WHITE = 2, + SPVC_MSL_SAMPLER_BORDER_COLOR_INT_MAX = 0x7fffffff +} spvc_msl_sampler_border_color; + +/* Maps to C++ API. */ +typedef enum spvc_msl_format_resolution +{ + SPVC_MSL_FORMAT_RESOLUTION_444 = 0, + SPVC_MSL_FORMAT_RESOLUTION_422, + SPVC_MSL_FORMAT_RESOLUTION_420, + SPVC_MSL_FORMAT_RESOLUTION_INT_MAX = 0x7fffffff +} spvc_msl_format_resolution; + +/* Maps to C++ API. */ +typedef enum spvc_msl_chroma_location +{ + SPVC_MSL_CHROMA_LOCATION_COSITED_EVEN = 0, + SPVC_MSL_CHROMA_LOCATION_MIDPOINT, + SPVC_MSL_CHROMA_LOCATION_INT_MAX = 0x7fffffff +} spvc_msl_chroma_location; + +/* Maps to C++ API. */ +typedef enum spvc_msl_component_swizzle +{ + SPVC_MSL_COMPONENT_SWIZZLE_IDENTITY = 0, + SPVC_MSL_COMPONENT_SWIZZLE_ZERO, + SPVC_MSL_COMPONENT_SWIZZLE_ONE, + SPVC_MSL_COMPONENT_SWIZZLE_R, + SPVC_MSL_COMPONENT_SWIZZLE_G, + SPVC_MSL_COMPONENT_SWIZZLE_B, + SPVC_MSL_COMPONENT_SWIZZLE_A, + SPVC_MSL_COMPONENT_SWIZZLE_INT_MAX = 0x7fffffff +} spvc_msl_component_swizzle; + +/* Maps to C++ API. */ +typedef enum spvc_msl_sampler_ycbcr_model_conversion +{ + SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0, + SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY, + SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_709, + SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_601, + SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_2020, + SPVC_MSL_SAMPLER_YCBCR_MODEL_CONVERSION_INT_MAX = 0x7fffffff +} spvc_msl_sampler_ycbcr_model_conversion; + +/* Maps to C+ API. */ +typedef enum spvc_msl_sampler_ycbcr_range +{ + SPVC_MSL_SAMPLER_YCBCR_RANGE_ITU_FULL = 0, + SPVC_MSL_SAMPLER_YCBCR_RANGE_ITU_NARROW, + SPVC_MSL_SAMPLER_YCBCR_RANGE_INT_MAX = 0x7fffffff +} spvc_msl_sampler_ycbcr_range; + +/* Maps to C++ API. */ +typedef struct spvc_msl_constexpr_sampler +{ + spvc_msl_sampler_coord coord; + spvc_msl_sampler_filter min_filter; + spvc_msl_sampler_filter mag_filter; + spvc_msl_sampler_mip_filter mip_filter; + spvc_msl_sampler_address s_address; + spvc_msl_sampler_address t_address; + spvc_msl_sampler_address r_address; + spvc_msl_sampler_compare_func compare_func; + spvc_msl_sampler_border_color border_color; + float lod_clamp_min; + float lod_clamp_max; + int max_anisotropy; + + spvc_bool compare_enable; + spvc_bool lod_clamp_enable; + spvc_bool anisotropy_enable; +} spvc_msl_constexpr_sampler; + +/* + * Initializes the constexpr sampler struct. + * The defaults are non-zero. + */ +SPVC_PUBLIC_API void spvc_msl_constexpr_sampler_init(spvc_msl_constexpr_sampler *sampler); + +/* Maps to the sampler Y'CbCr conversion-related portions of MSLConstexprSampler. See C++ API for defaults and details. */ +typedef struct spvc_msl_sampler_ycbcr_conversion +{ + unsigned planes; + spvc_msl_format_resolution resolution; + spvc_msl_sampler_filter chroma_filter; + spvc_msl_chroma_location x_chroma_offset; + spvc_msl_chroma_location y_chroma_offset; + spvc_msl_component_swizzle swizzle[4]; + spvc_msl_sampler_ycbcr_model_conversion ycbcr_model; + spvc_msl_sampler_ycbcr_range ycbcr_range; + unsigned bpc; +} spvc_msl_sampler_ycbcr_conversion; + +/* + * Initializes the constexpr sampler struct. + * The defaults are non-zero. + */ +SPVC_PUBLIC_API void spvc_msl_sampler_ycbcr_conversion_init(spvc_msl_sampler_ycbcr_conversion *conv); + +/* Maps to C++ API. */ +typedef enum spvc_hlsl_binding_flag_bits +{ + SPVC_HLSL_BINDING_AUTO_NONE_BIT = 0, + SPVC_HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT = 1 << 0, + SPVC_HLSL_BINDING_AUTO_CBV_BIT = 1 << 1, + SPVC_HLSL_BINDING_AUTO_SRV_BIT = 1 << 2, + SPVC_HLSL_BINDING_AUTO_UAV_BIT = 1 << 3, + SPVC_HLSL_BINDING_AUTO_SAMPLER_BIT = 1 << 4, + SPVC_HLSL_BINDING_AUTO_ALL = 0x7fffffff +} spvc_hlsl_binding_flag_bits; +typedef unsigned spvc_hlsl_binding_flags; + +#define SPVC_HLSL_PUSH_CONSTANT_DESC_SET (~(0u)) +#define SPVC_HLSL_PUSH_CONSTANT_BINDING (0) + +/* Maps to C++ API. */ +typedef struct spvc_hlsl_resource_binding_mapping +{ + unsigned register_space; + unsigned register_binding; +} spvc_hlsl_resource_binding_mapping; + +typedef struct spvc_hlsl_resource_binding +{ + SpvExecutionModel stage; + unsigned desc_set; + unsigned binding; + + spvc_hlsl_resource_binding_mapping cbv, uav, srv, sampler; +} spvc_hlsl_resource_binding; + +/* + * Initializes the resource binding struct. + * The defaults are non-zero. + */ +SPVC_PUBLIC_API void spvc_hlsl_resource_binding_init(spvc_hlsl_resource_binding *binding); + +/* Maps to the various spirv_cross::Compiler*::Option structures. See C++ API for defaults and details. */ +typedef enum spvc_compiler_option +{ + SPVC_COMPILER_OPTION_UNKNOWN = 0, + + SPVC_COMPILER_OPTION_FORCE_TEMPORARY = 1 | SPVC_COMPILER_OPTION_COMMON_BIT, + SPVC_COMPILER_OPTION_FLATTEN_MULTIDIMENSIONAL_ARRAYS = 2 | SPVC_COMPILER_OPTION_COMMON_BIT, + SPVC_COMPILER_OPTION_FIXUP_DEPTH_CONVENTION = 3 | SPVC_COMPILER_OPTION_COMMON_BIT, + SPVC_COMPILER_OPTION_FLIP_VERTEX_Y = 4 | SPVC_COMPILER_OPTION_COMMON_BIT, + + SPVC_COMPILER_OPTION_GLSL_SUPPORT_NONZERO_BASE_INSTANCE = 5 | SPVC_COMPILER_OPTION_GLSL_BIT, + SPVC_COMPILER_OPTION_GLSL_SEPARATE_SHADER_OBJECTS = 6 | SPVC_COMPILER_OPTION_GLSL_BIT, + SPVC_COMPILER_OPTION_GLSL_ENABLE_420PACK_EXTENSION = 7 | SPVC_COMPILER_OPTION_GLSL_BIT, + SPVC_COMPILER_OPTION_GLSL_VERSION = 8 | SPVC_COMPILER_OPTION_GLSL_BIT, + SPVC_COMPILER_OPTION_GLSL_ES = 9 | SPVC_COMPILER_OPTION_GLSL_BIT, + SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS = 10 | SPVC_COMPILER_OPTION_GLSL_BIT, + SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_FLOAT_PRECISION_HIGHP = 11 | SPVC_COMPILER_OPTION_GLSL_BIT, + SPVC_COMPILER_OPTION_GLSL_ES_DEFAULT_INT_PRECISION_HIGHP = 12 | SPVC_COMPILER_OPTION_GLSL_BIT, + + SPVC_COMPILER_OPTION_HLSL_SHADER_MODEL = 13 | SPVC_COMPILER_OPTION_HLSL_BIT, + SPVC_COMPILER_OPTION_HLSL_POINT_SIZE_COMPAT = 14 | SPVC_COMPILER_OPTION_HLSL_BIT, + SPVC_COMPILER_OPTION_HLSL_POINT_COORD_COMPAT = 15 | SPVC_COMPILER_OPTION_HLSL_BIT, + SPVC_COMPILER_OPTION_HLSL_SUPPORT_NONZERO_BASE_VERTEX_BASE_INSTANCE = 16 | SPVC_COMPILER_OPTION_HLSL_BIT, + + SPVC_COMPILER_OPTION_MSL_VERSION = 17 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_TEXEL_BUFFER_TEXTURE_WIDTH = 18 | SPVC_COMPILER_OPTION_MSL_BIT, + + /* Obsolete, use SWIZZLE_BUFFER_INDEX instead. */ + SPVC_COMPILER_OPTION_MSL_AUX_BUFFER_INDEX = 19 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_SWIZZLE_BUFFER_INDEX = 19 | SPVC_COMPILER_OPTION_MSL_BIT, + + SPVC_COMPILER_OPTION_MSL_INDIRECT_PARAMS_BUFFER_INDEX = 20 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_SHADER_OUTPUT_BUFFER_INDEX = 21 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_SHADER_PATCH_OUTPUT_BUFFER_INDEX = 22 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_SHADER_TESS_FACTOR_OUTPUT_BUFFER_INDEX = 23 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_WORKGROUP_INDEX = 24 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_ENABLE_POINT_SIZE_BUILTIN = 25 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_DISABLE_RASTERIZATION = 26 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_CAPTURE_OUTPUT_TO_BUFFER = 27 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_SWIZZLE_TEXTURE_SAMPLES = 28 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_PAD_FRAGMENT_OUTPUT_COMPONENTS = 29 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_TESS_DOMAIN_ORIGIN_LOWER_LEFT = 30 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_PLATFORM = 31 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_ARGUMENT_BUFFERS = 32 | SPVC_COMPILER_OPTION_MSL_BIT, + + SPVC_COMPILER_OPTION_GLSL_EMIT_PUSH_CONSTANT_AS_UNIFORM_BUFFER = 33 | SPVC_COMPILER_OPTION_GLSL_BIT, + + SPVC_COMPILER_OPTION_MSL_TEXTURE_BUFFER_NATIVE = 34 | SPVC_COMPILER_OPTION_MSL_BIT, + + SPVC_COMPILER_OPTION_GLSL_EMIT_UNIFORM_BUFFER_AS_PLAIN_UNIFORMS = 35 | SPVC_COMPILER_OPTION_GLSL_BIT, + + SPVC_COMPILER_OPTION_MSL_BUFFER_SIZE_BUFFER_INDEX = 36 | SPVC_COMPILER_OPTION_MSL_BIT, + + SPVC_COMPILER_OPTION_EMIT_LINE_DIRECTIVES = 37 | SPVC_COMPILER_OPTION_COMMON_BIT, + + SPVC_COMPILER_OPTION_MSL_MULTIVIEW = 38 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_VIEW_MASK_BUFFER_INDEX = 39 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_DEVICE_INDEX = 40 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_VIEW_INDEX_FROM_DEVICE_INDEX = 41 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_DISPATCH_BASE = 42 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_DYNAMIC_OFFSETS_BUFFER_INDEX = 43 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_TEXTURE_1D_AS_2D = 44 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_ENABLE_BASE_INDEX_ZERO = 45 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_IOS_FRAMEBUFFER_FETCH_SUBPASS = 46 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_INVARIANT_FP_MATH = 47 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_EMULATE_CUBEMAP_ARRAY = 48 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING = 49 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_FORCE_ACTIVE_ARGUMENT_BUFFER_RESOURCES = 50 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_FORCE_NATIVE_ARRAYS = 51 | SPVC_COMPILER_OPTION_MSL_BIT, + + SPVC_COMPILER_OPTION_ENABLE_STORAGE_IMAGE_QUALIFIER_DEDUCTION = 52 | SPVC_COMPILER_OPTION_COMMON_BIT, + + SPVC_COMPILER_OPTION_HLSL_FORCE_STORAGE_BUFFER_AS_UAV = 53 | SPVC_COMPILER_OPTION_HLSL_BIT, + + SPVC_COMPILER_OPTION_FORCE_ZERO_INITIALIZED_VARIABLES = 54 | SPVC_COMPILER_OPTION_COMMON_BIT, + + SPVC_COMPILER_OPTION_HLSL_NONWRITABLE_UAV_TEXTURE_AS_SRV = 55 | SPVC_COMPILER_OPTION_HLSL_BIT, + + SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_OUTPUT_MASK = 56 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_DEPTH_BUILTIN = 57 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_ENABLE_FRAG_STENCIL_REF_BUILTIN = 58 | SPVC_COMPILER_OPTION_MSL_BIT, + SPVC_COMPILER_OPTION_MSL_ENABLE_CLIP_DISTANCE_USER_VARYING = 59 | SPVC_COMPILER_OPTION_MSL_BIT, + + SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff +} spvc_compiler_option; + +/* + * Context is the highest-level API construct. + * The context owns all memory allocations made by its child object hierarchy, including various non-opaque structs and strings. + * This means that the API user only has to care about one "destroy" call ever when using the C API. + * All pointers handed out by the APIs are only valid as long as the context + * is alive and spvc_context_release_allocations has not been called. + */ +SPVC_PUBLIC_API spvc_result spvc_context_create(spvc_context *context); + +/* Frees all memory allocations and objects associated with the context and its child objects. */ +SPVC_PUBLIC_API void spvc_context_destroy(spvc_context context); + +/* Frees all memory allocations and objects associated with the context and its child objects, but keeps the context alive. */ +SPVC_PUBLIC_API void spvc_context_release_allocations(spvc_context context); + +/* Get the string for the last error which was logged. */ +SPVC_PUBLIC_API const char *spvc_context_get_last_error_string(spvc_context context); + +/* Get notified in a callback when an error triggers. Useful for debugging. */ +typedef void (*spvc_error_callback)(void *userdata, const char *error); +SPVC_PUBLIC_API void spvc_context_set_error_callback(spvc_context context, spvc_error_callback cb, void *userdata); + +/* SPIR-V parsing interface. Maps to Parser which then creates a ParsedIR, and that IR is extracted into the handle. */ +SPVC_PUBLIC_API spvc_result spvc_context_parse_spirv(spvc_context context, const SpvId *spirv, size_t word_count, + spvc_parsed_ir *parsed_ir); + +/* + * Create a compiler backend. Capture mode controls if we construct by copy or move semantics. + * It is always recommended to use SPVC_CAPTURE_MODE_TAKE_OWNERSHIP if you only intend to cross-compile the IR once. + */ +SPVC_PUBLIC_API spvc_result spvc_context_create_compiler(spvc_context context, spvc_backend backend, + spvc_parsed_ir parsed_ir, spvc_capture_mode mode, + spvc_compiler *compiler); + +/* Maps directly to C++ API. */ +SPVC_PUBLIC_API unsigned spvc_compiler_get_current_id_bound(spvc_compiler compiler); + +/* Create compiler options, which will initialize defaults. */ +SPVC_PUBLIC_API spvc_result spvc_compiler_create_compiler_options(spvc_compiler compiler, + spvc_compiler_options *options); +/* Override options. Will return error if e.g. MSL options are used for the HLSL backend, etc. */ +SPVC_PUBLIC_API spvc_result spvc_compiler_options_set_bool(spvc_compiler_options options, + spvc_compiler_option option, spvc_bool value); +SPVC_PUBLIC_API spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, + spvc_compiler_option option, unsigned value); +/* Set compiler options. */ +SPVC_PUBLIC_API spvc_result spvc_compiler_install_compiler_options(spvc_compiler compiler, + spvc_compiler_options options); + +/* Compile IR into a string. *source is owned by the context, and caller must not free it themselves. */ +SPVC_PUBLIC_API spvc_result spvc_compiler_compile(spvc_compiler compiler, const char **source); + +/* Maps to C++ API. */ +SPVC_PUBLIC_API spvc_result spvc_compiler_add_header_line(spvc_compiler compiler, const char *line); +SPVC_PUBLIC_API spvc_result spvc_compiler_require_extension(spvc_compiler compiler, const char *ext); +SPVC_PUBLIC_API spvc_result spvc_compiler_flatten_buffer_block(spvc_compiler compiler, spvc_variable_id id); + +SPVC_PUBLIC_API spvc_bool spvc_compiler_variable_is_depth_or_compare(spvc_compiler compiler, spvc_variable_id id); + +/* + * HLSL specifics. + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_result spvc_compiler_hlsl_set_root_constants_layout(spvc_compiler compiler, + const spvc_hlsl_root_constants *constant_info, + size_t count); +SPVC_PUBLIC_API spvc_result spvc_compiler_hlsl_add_vertex_attribute_remap(spvc_compiler compiler, + const spvc_hlsl_vertex_attribute_remap *remap, + size_t remaps); +SPVC_PUBLIC_API spvc_variable_id spvc_compiler_hlsl_remap_num_workgroups_builtin(spvc_compiler compiler); + +SPVC_PUBLIC_API spvc_result spvc_compiler_hlsl_set_resource_binding_flags(spvc_compiler compiler, + spvc_hlsl_binding_flags flags); + +SPVC_PUBLIC_API spvc_result spvc_compiler_hlsl_add_resource_binding(spvc_compiler compiler, + const spvc_hlsl_resource_binding *binding); +SPVC_PUBLIC_API spvc_bool spvc_compiler_hlsl_is_resource_used(spvc_compiler compiler, + SpvExecutionModel model, + unsigned set, + unsigned binding); + +/* + * MSL specifics. + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_rasterization_disabled(spvc_compiler compiler); + +/* Obsolete. Renamed to needs_swizzle_buffer. */ +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_aux_buffer(spvc_compiler compiler); +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_swizzle_buffer(spvc_compiler compiler); +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_buffer_size_buffer(spvc_compiler compiler); + +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_output_buffer(spvc_compiler compiler); +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_patch_output_buffer(spvc_compiler compiler); +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_needs_input_threadgroup_mem(spvc_compiler compiler); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_vertex_attribute(spvc_compiler compiler, + const spvc_msl_vertex_attribute *attrs); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_resource_binding(spvc_compiler compiler, + const spvc_msl_resource_binding *binding); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_discrete_descriptor_set(spvc_compiler compiler, unsigned desc_set); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_argument_buffer_device_address_space(spvc_compiler compiler, unsigned desc_set, spvc_bool device_address); +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler, unsigned location); +SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compiler, + SpvExecutionModel model, + unsigned set, + unsigned binding); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_remap_constexpr_sampler(spvc_compiler compiler, spvc_variable_id id, const spvc_msl_constexpr_sampler *sampler); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_remap_constexpr_sampler_by_binding(spvc_compiler compiler, unsigned desc_set, unsigned binding, const spvc_msl_constexpr_sampler *sampler); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_remap_constexpr_sampler_ycbcr(spvc_compiler compiler, spvc_variable_id id, const spvc_msl_constexpr_sampler *sampler, const spvc_msl_sampler_ycbcr_conversion *conv); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_remap_constexpr_sampler_by_binding_ycbcr(spvc_compiler compiler, unsigned desc_set, unsigned binding, const spvc_msl_constexpr_sampler *sampler, const spvc_msl_sampler_ycbcr_conversion *conv); +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_fragment_output_components(spvc_compiler compiler, unsigned location, unsigned components); + +SPVC_PUBLIC_API unsigned spvc_compiler_msl_get_automatic_resource_binding(spvc_compiler compiler, spvc_variable_id id); +SPVC_PUBLIC_API unsigned spvc_compiler_msl_get_automatic_resource_binding_secondary(spvc_compiler compiler, spvc_variable_id id); + +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_dynamic_buffer(spvc_compiler compiler, unsigned desc_set, unsigned binding, unsigned index); + +SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_inline_uniform_block(spvc_compiler compiler, unsigned desc_set, unsigned binding); + +/* + * Reflect resources. + * Maps almost 1:1 to C++ API. + */ +SPVC_PUBLIC_API spvc_result spvc_compiler_get_active_interface_variables(spvc_compiler compiler, spvc_set *set); +SPVC_PUBLIC_API spvc_result spvc_compiler_set_enabled_interface_variables(spvc_compiler compiler, spvc_set set); +SPVC_PUBLIC_API spvc_result spvc_compiler_create_shader_resources(spvc_compiler compiler, spvc_resources *resources); +SPVC_PUBLIC_API spvc_result spvc_compiler_create_shader_resources_for_active_variables(spvc_compiler compiler, + spvc_resources *resources, + spvc_set active); +SPVC_PUBLIC_API spvc_result spvc_resources_get_resource_list_for_type(spvc_resources resources, spvc_resource_type type, + const spvc_reflected_resource **resource_list, + size_t *resource_size); + +/* + * Decorations. + * Maps to C++ API. + */ +SPVC_PUBLIC_API void spvc_compiler_set_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration, + unsigned argument); +SPVC_PUBLIC_API void spvc_compiler_set_decoration_string(spvc_compiler compiler, SpvId id, SpvDecoration decoration, + const char *argument); +SPVC_PUBLIC_API void spvc_compiler_set_name(spvc_compiler compiler, SpvId id, const char *argument); +SPVC_PUBLIC_API void spvc_compiler_set_member_decoration(spvc_compiler compiler, spvc_type_id id, unsigned member_index, + SpvDecoration decoration, unsigned argument); +SPVC_PUBLIC_API void spvc_compiler_set_member_decoration_string(spvc_compiler compiler, spvc_type_id id, + unsigned member_index, SpvDecoration decoration, + const char *argument); +SPVC_PUBLIC_API void spvc_compiler_set_member_name(spvc_compiler compiler, spvc_type_id id, unsigned member_index, + const char *argument); +SPVC_PUBLIC_API void spvc_compiler_unset_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration); +SPVC_PUBLIC_API void spvc_compiler_unset_member_decoration(spvc_compiler compiler, spvc_type_id id, + unsigned member_index, SpvDecoration decoration); + +SPVC_PUBLIC_API spvc_bool spvc_compiler_has_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration); +SPVC_PUBLIC_API spvc_bool spvc_compiler_has_member_decoration(spvc_compiler compiler, spvc_type_id id, + unsigned member_index, SpvDecoration decoration); +SPVC_PUBLIC_API const char *spvc_compiler_get_name(spvc_compiler compiler, SpvId id); +SPVC_PUBLIC_API unsigned spvc_compiler_get_decoration(spvc_compiler compiler, SpvId id, SpvDecoration decoration); +SPVC_PUBLIC_API const char *spvc_compiler_get_decoration_string(spvc_compiler compiler, SpvId id, + SpvDecoration decoration); +SPVC_PUBLIC_API unsigned spvc_compiler_get_member_decoration(spvc_compiler compiler, spvc_type_id id, + unsigned member_index, SpvDecoration decoration); +SPVC_PUBLIC_API const char *spvc_compiler_get_member_decoration_string(spvc_compiler compiler, spvc_type_id id, + unsigned member_index, SpvDecoration decoration); +SPVC_PUBLIC_API const char *spvc_compiler_get_member_name(spvc_compiler compiler, spvc_type_id id, unsigned member_index); + +/* + * Entry points. + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_result spvc_compiler_get_entry_points(spvc_compiler compiler, + const spvc_entry_point **entry_points, + size_t *num_entry_points); +SPVC_PUBLIC_API spvc_result spvc_compiler_set_entry_point(spvc_compiler compiler, const char *name, + SpvExecutionModel model); +SPVC_PUBLIC_API spvc_result spvc_compiler_rename_entry_point(spvc_compiler compiler, const char *old_name, + const char *new_name, SpvExecutionModel model); +SPVC_PUBLIC_API const char *spvc_compiler_get_cleansed_entry_point_name(spvc_compiler compiler, const char *name, + SpvExecutionModel model); +SPVC_PUBLIC_API void spvc_compiler_set_execution_mode(spvc_compiler compiler, SpvExecutionMode mode); +SPVC_PUBLIC_API void spvc_compiler_unset_execution_mode(spvc_compiler compiler, SpvExecutionMode mode); +SPVC_PUBLIC_API void spvc_compiler_set_execution_mode_with_arguments(spvc_compiler compiler, SpvExecutionMode mode, + unsigned arg0, unsigned arg1, unsigned arg2); +SPVC_PUBLIC_API spvc_result spvc_compiler_get_execution_modes(spvc_compiler compiler, const SpvExecutionMode **modes, + size_t *num_modes); +SPVC_PUBLIC_API unsigned spvc_compiler_get_execution_mode_argument(spvc_compiler compiler, SpvExecutionMode mode); +SPVC_PUBLIC_API unsigned spvc_compiler_get_execution_mode_argument_by_index(spvc_compiler compiler, + SpvExecutionMode mode, unsigned index); +SPVC_PUBLIC_API SpvExecutionModel spvc_compiler_get_execution_model(spvc_compiler compiler); + +/* + * Type query interface. + * Maps to C++ API, except it's read-only. + */ +SPVC_PUBLIC_API spvc_type spvc_compiler_get_type_handle(spvc_compiler compiler, spvc_type_id id); + +/* Pulls out SPIRType::self. This effectively gives the type ID without array or pointer qualifiers. + * This is necessary when reflecting decoration/name information on members of a struct, + * which are placed in the base type, not the qualified type. + * This is similar to spvc_reflected_resource::base_type_id. */ +SPVC_PUBLIC_API spvc_type_id spvc_type_get_base_type_id(spvc_type type); + +SPVC_PUBLIC_API spvc_basetype spvc_type_get_basetype(spvc_type type); +SPVC_PUBLIC_API unsigned spvc_type_get_bit_width(spvc_type type); +SPVC_PUBLIC_API unsigned spvc_type_get_vector_size(spvc_type type); +SPVC_PUBLIC_API unsigned spvc_type_get_columns(spvc_type type); +SPVC_PUBLIC_API unsigned spvc_type_get_num_array_dimensions(spvc_type type); +SPVC_PUBLIC_API spvc_bool spvc_type_array_dimension_is_literal(spvc_type type, unsigned dimension); +SPVC_PUBLIC_API SpvId spvc_type_get_array_dimension(spvc_type type, unsigned dimension); +SPVC_PUBLIC_API unsigned spvc_type_get_num_member_types(spvc_type type); +SPVC_PUBLIC_API spvc_type_id spvc_type_get_member_type(spvc_type type, unsigned index); +SPVC_PUBLIC_API SpvStorageClass spvc_type_get_storage_class(spvc_type type); + +/* Image type query. */ +SPVC_PUBLIC_API spvc_type_id spvc_type_get_image_sampled_type(spvc_type type); +SPVC_PUBLIC_API SpvDim spvc_type_get_image_dimension(spvc_type type); +SPVC_PUBLIC_API spvc_bool spvc_type_get_image_is_depth(spvc_type type); +SPVC_PUBLIC_API spvc_bool spvc_type_get_image_arrayed(spvc_type type); +SPVC_PUBLIC_API spvc_bool spvc_type_get_image_multisampled(spvc_type type); +SPVC_PUBLIC_API spvc_bool spvc_type_get_image_is_storage(spvc_type type); +SPVC_PUBLIC_API SpvImageFormat spvc_type_get_image_storage_format(spvc_type type); +SPVC_PUBLIC_API SpvAccessQualifier spvc_type_get_image_access_qualifier(spvc_type type); + +/* + * Buffer layout query. + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_result spvc_compiler_get_declared_struct_size(spvc_compiler compiler, spvc_type struct_type, size_t *size); +SPVC_PUBLIC_API spvc_result spvc_compiler_get_declared_struct_size_runtime_array(spvc_compiler compiler, + spvc_type struct_type, size_t array_size, size_t *size); +SPVC_PUBLIC_API spvc_result spvc_compiler_get_declared_struct_member_size(spvc_compiler compiler, spvc_type type, unsigned index, size_t *size); + +SPVC_PUBLIC_API spvc_result spvc_compiler_type_struct_member_offset(spvc_compiler compiler, + spvc_type type, unsigned index, unsigned *offset); +SPVC_PUBLIC_API spvc_result spvc_compiler_type_struct_member_array_stride(spvc_compiler compiler, + spvc_type type, unsigned index, unsigned *stride); +SPVC_PUBLIC_API spvc_result spvc_compiler_type_struct_member_matrix_stride(spvc_compiler compiler, + spvc_type type, unsigned index, unsigned *stride); + +/* + * Workaround helper functions. + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_result spvc_compiler_build_dummy_sampler_for_combined_images(spvc_compiler compiler, spvc_variable_id *id); +SPVC_PUBLIC_API spvc_result spvc_compiler_build_combined_image_samplers(spvc_compiler compiler); +SPVC_PUBLIC_API spvc_result spvc_compiler_get_combined_image_samplers(spvc_compiler compiler, + const spvc_combined_image_sampler **samplers, + size_t *num_samplers); + +/* + * Constants + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_result spvc_compiler_get_specialization_constants(spvc_compiler compiler, + const spvc_specialization_constant **constants, + size_t *num_constants); +SPVC_PUBLIC_API spvc_constant spvc_compiler_get_constant_handle(spvc_compiler compiler, + spvc_constant_id id); + +SPVC_PUBLIC_API spvc_constant_id spvc_compiler_get_work_group_size_specialization_constants(spvc_compiler compiler, + spvc_specialization_constant *x, + spvc_specialization_constant *y, + spvc_specialization_constant *z); + +/* + * Buffer ranges + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_result spvc_compiler_get_active_buffer_ranges(spvc_compiler compiler, + spvc_variable_id id, + const spvc_buffer_range **ranges, + size_t *num_ranges); + +/* + * No stdint.h until C99, sigh :( + * For smaller types, the result is sign or zero-extended as appropriate. + * Maps to C++ API. + * TODO: The SPIRConstant query interface and modification interface is not quite complete. + */ +SPVC_PUBLIC_API float spvc_constant_get_scalar_fp16(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API float spvc_constant_get_scalar_fp32(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API double spvc_constant_get_scalar_fp64(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API unsigned spvc_constant_get_scalar_u32(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API int spvc_constant_get_scalar_i32(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API unsigned spvc_constant_get_scalar_u16(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API int spvc_constant_get_scalar_i16(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API unsigned spvc_constant_get_scalar_u8(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API int spvc_constant_get_scalar_i8(spvc_constant constant, unsigned column, unsigned row); +SPVC_PUBLIC_API void spvc_constant_get_subconstants(spvc_constant constant, const spvc_constant_id **constituents, size_t *count); +SPVC_PUBLIC_API spvc_type_id spvc_constant_get_type(spvc_constant constant); + +/* + * Misc reflection + * Maps to C++ API. + */ +SPVC_PUBLIC_API spvc_bool spvc_compiler_get_binary_offset_for_decoration(spvc_compiler compiler, + spvc_variable_id id, + SpvDecoration decoration, + unsigned *word_offset); + +SPVC_PUBLIC_API spvc_bool spvc_compiler_buffer_is_hlsl_counter_buffer(spvc_compiler compiler, spvc_variable_id id); +SPVC_PUBLIC_API spvc_bool spvc_compiler_buffer_get_hlsl_counter_buffer(spvc_compiler compiler, spvc_variable_id id, + spvc_variable_id *counter_id); + +SPVC_PUBLIC_API spvc_result spvc_compiler_get_declared_capabilities(spvc_compiler compiler, + const SpvCapability **capabilities, + size_t *num_capabilities); +SPVC_PUBLIC_API spvc_result spvc_compiler_get_declared_extensions(spvc_compiler compiler, const char ***extensions, + size_t *num_extensions); + +SPVC_PUBLIC_API const char *spvc_compiler_get_remapped_declared_block_name(spvc_compiler compiler, spvc_variable_id id); +SPVC_PUBLIC_API spvc_result spvc_compiler_get_buffer_block_decorations(spvc_compiler compiler, spvc_variable_id id, + const SpvDecoration **decorations, + size_t *num_decorations); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ios/include/spirv_cross/spirv_cross_containers.hpp b/ios/include/spirv_cross/spirv_cross_containers.hpp new file mode 100644 index 00000000..f5760a0e --- /dev/null +++ b/ios/include/spirv_cross/spirv_cross_containers.hpp @@ -0,0 +1,734 @@ +/* + * Copyright 2019-2020 Hans-Kristian Arntzen + * + * 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 SPIRV_CROSS_CONTAINERS_HPP +#define SPIRV_CROSS_CONTAINERS_HPP + +#include "spirv_cross_error_handling.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SPIRV_CROSS_NAMESPACE_OVERRIDE +#define SPIRV_CROSS_NAMESPACE SPIRV_CROSS_NAMESPACE_OVERRIDE +#else +#define SPIRV_CROSS_NAMESPACE spirv_cross +#endif + +namespace SPIRV_CROSS_NAMESPACE +{ +#ifndef SPIRV_CROSS_FORCE_STL_TYPES +// std::aligned_storage does not support size == 0, so roll our own. +template +class AlignedBuffer +{ +public: + T *data() + { +#if defined(_MSC_VER) && _MSC_VER < 1900 + // MSVC 2013 workarounds, sigh ... + // Only use this workaround on MSVC 2013 due to some confusion around default initialized unions. + // Spec seems to suggest the memory will be zero-initialized, which is *not* what we want. + return reinterpret_cast(u.aligned_char); +#else + return reinterpret_cast(aligned_char); +#endif + } + +private: +#if defined(_MSC_VER) && _MSC_VER < 1900 + // MSVC 2013 workarounds, sigh ... + union { + char aligned_char[sizeof(T) * N]; + double dummy_aligner; + } u; +#else + alignas(T) char aligned_char[sizeof(T) * N]; +#endif +}; + +template +class AlignedBuffer +{ +public: + T *data() + { + return nullptr; + } +}; + +// An immutable version of SmallVector which erases type information about storage. +template +class VectorView +{ +public: + T &operator[](size_t i) SPIRV_CROSS_NOEXCEPT + { + return ptr[i]; + } + + const T &operator[](size_t i) const SPIRV_CROSS_NOEXCEPT + { + return ptr[i]; + } + + bool empty() const SPIRV_CROSS_NOEXCEPT + { + return buffer_size == 0; + } + + size_t size() const SPIRV_CROSS_NOEXCEPT + { + return buffer_size; + } + + T *data() SPIRV_CROSS_NOEXCEPT + { + return ptr; + } + + const T *data() const SPIRV_CROSS_NOEXCEPT + { + return ptr; + } + + T *begin() SPIRV_CROSS_NOEXCEPT + { + return ptr; + } + + T *end() SPIRV_CROSS_NOEXCEPT + { + return ptr + buffer_size; + } + + const T *begin() const SPIRV_CROSS_NOEXCEPT + { + return ptr; + } + + const T *end() const SPIRV_CROSS_NOEXCEPT + { + return ptr + buffer_size; + } + + T &front() SPIRV_CROSS_NOEXCEPT + { + return ptr[0]; + } + + const T &front() const SPIRV_CROSS_NOEXCEPT + { + return ptr[0]; + } + + T &back() SPIRV_CROSS_NOEXCEPT + { + return ptr[buffer_size - 1]; + } + + const T &back() const SPIRV_CROSS_NOEXCEPT + { + return ptr[buffer_size - 1]; + } + + // Makes it easier to consume SmallVector. +#if defined(_MSC_VER) && _MSC_VER < 1900 + explicit operator std::vector() const + { + // Another MSVC 2013 workaround. It does not understand lvalue/rvalue qualified operations. + return std::vector(ptr, ptr + buffer_size); + } +#else + // Makes it easier to consume SmallVector. + explicit operator std::vector() const & + { + return std::vector(ptr, ptr + buffer_size); + } + + // If we are converting as an r-value, we can pilfer our elements. + explicit operator std::vector() && + { + return std::vector(std::make_move_iterator(ptr), std::make_move_iterator(ptr + buffer_size)); + } +#endif + + // Avoid sliced copies. Base class should only be read as a reference. + VectorView(const VectorView &) = delete; + void operator=(const VectorView &) = delete; + +protected: + VectorView() = default; + T *ptr = nullptr; + size_t buffer_size = 0; +}; + +// Simple vector which supports up to N elements inline, without malloc/free. +// We use a lot of throwaway vectors all over the place which triggers allocations. +// This class only implements the subset of std::vector we need in SPIRV-Cross. +// It is *NOT* a drop-in replacement in general projects. +template +class SmallVector : public VectorView +{ +public: + SmallVector() SPIRV_CROSS_NOEXCEPT + { + this->ptr = stack_storage.data(); + buffer_capacity = N; + } + + SmallVector(const T *arg_list_begin, const T *arg_list_end) SPIRV_CROSS_NOEXCEPT : SmallVector() + { + auto count = size_t(arg_list_end - arg_list_begin); + reserve(count); + for (size_t i = 0; i < count; i++, arg_list_begin++) + new (&this->ptr[i]) T(*arg_list_begin); + this->buffer_size = count; + } + + SmallVector(SmallVector &&other) SPIRV_CROSS_NOEXCEPT : SmallVector() + { + *this = std::move(other); + } + + SmallVector &operator=(SmallVector &&other) SPIRV_CROSS_NOEXCEPT + { + clear(); + if (other.ptr != other.stack_storage.data()) + { + // Pilfer allocated pointer. + if (this->ptr != stack_storage.data()) + free(this->ptr); + this->ptr = other.ptr; + this->buffer_size = other.buffer_size; + buffer_capacity = other.buffer_capacity; + other.ptr = nullptr; + other.buffer_size = 0; + other.buffer_capacity = 0; + } + else + { + // Need to move the stack contents individually. + reserve(other.buffer_size); + for (size_t i = 0; i < other.buffer_size; i++) + { + new (&this->ptr[i]) T(std::move(other.ptr[i])); + other.ptr[i].~T(); + } + this->buffer_size = other.buffer_size; + other.buffer_size = 0; + } + return *this; + } + + SmallVector(const SmallVector &other) SPIRV_CROSS_NOEXCEPT : SmallVector() + { + *this = other; + } + + SmallVector &operator=(const SmallVector &other) SPIRV_CROSS_NOEXCEPT + { + if (this == &other) + return *this; + + clear(); + reserve(other.buffer_size); + for (size_t i = 0; i < other.buffer_size; i++) + new (&this->ptr[i]) T(other.ptr[i]); + this->buffer_size = other.buffer_size; + return *this; + } + + explicit SmallVector(size_t count) SPIRV_CROSS_NOEXCEPT : SmallVector() + { + resize(count); + } + + ~SmallVector() + { + clear(); + if (this->ptr != stack_storage.data()) + free(this->ptr); + } + + void clear() SPIRV_CROSS_NOEXCEPT + { + for (size_t i = 0; i < this->buffer_size; i++) + this->ptr[i].~T(); + this->buffer_size = 0; + } + + void push_back(const T &t) SPIRV_CROSS_NOEXCEPT + { + reserve(this->buffer_size + 1); + new (&this->ptr[this->buffer_size]) T(t); + this->buffer_size++; + } + + void push_back(T &&t) SPIRV_CROSS_NOEXCEPT + { + reserve(this->buffer_size + 1); + new (&this->ptr[this->buffer_size]) T(std::move(t)); + this->buffer_size++; + } + + void pop_back() SPIRV_CROSS_NOEXCEPT + { + // Work around false positive warning on GCC 8.3. + // Calling pop_back on empty vector is undefined. + if (!this->empty()) + resize(this->buffer_size - 1); + } + + template + void emplace_back(Ts &&... ts) SPIRV_CROSS_NOEXCEPT + { + reserve(this->buffer_size + 1); + new (&this->ptr[this->buffer_size]) T(std::forward(ts)...); + this->buffer_size++; + } + + void reserve(size_t count) SPIRV_CROSS_NOEXCEPT + { + if ((count > std::numeric_limits::max() / sizeof(T)) || + (count > std::numeric_limits::max() / 2)) + { + // Only way this should ever happen is with garbage input, terminate. + std::terminate(); + } + + if (count > buffer_capacity) + { + size_t target_capacity = buffer_capacity; + if (target_capacity == 0) + target_capacity = 1; + if (target_capacity < N) + target_capacity = N; + + // Need to ensure there is a POT value of target capacity which is larger than count, + // otherwise this will overflow. + while (target_capacity < count) + target_capacity <<= 1u; + + T *new_buffer = + target_capacity > N ? static_cast(malloc(target_capacity * sizeof(T))) : stack_storage.data(); + + // If we actually fail this malloc, we are hosed anyways, there is no reason to attempt recovery. + if (!new_buffer) + std::terminate(); + + // In case for some reason two allocations both come from same stack. + if (new_buffer != this->ptr) + { + // We don't deal with types which can throw in move constructor. + for (size_t i = 0; i < this->buffer_size; i++) + { + new (&new_buffer[i]) T(std::move(this->ptr[i])); + this->ptr[i].~T(); + } + } + + if (this->ptr != stack_storage.data()) + free(this->ptr); + this->ptr = new_buffer; + buffer_capacity = target_capacity; + } + } + + void insert(T *itr, const T *insert_begin, const T *insert_end) SPIRV_CROSS_NOEXCEPT + { + auto count = size_t(insert_end - insert_begin); + if (itr == this->end()) + { + reserve(this->buffer_size + count); + for (size_t i = 0; i < count; i++, insert_begin++) + new (&this->ptr[this->buffer_size + i]) T(*insert_begin); + this->buffer_size += count; + } + else + { + if (this->buffer_size + count > buffer_capacity) + { + auto target_capacity = this->buffer_size + count; + if (target_capacity == 0) + target_capacity = 1; + if (target_capacity < N) + target_capacity = N; + + while (target_capacity < count) + target_capacity <<= 1u; + + // Need to allocate new buffer. Move everything to a new buffer. + T *new_buffer = + target_capacity > N ? static_cast(malloc(target_capacity * sizeof(T))) : stack_storage.data(); + + // If we actually fail this malloc, we are hosed anyways, there is no reason to attempt recovery. + if (!new_buffer) + std::terminate(); + + // First, move elements from source buffer to new buffer. + // We don't deal with types which can throw in move constructor. + auto *target_itr = new_buffer; + auto *original_source_itr = this->begin(); + + if (new_buffer != this->ptr) + { + while (original_source_itr != itr) + { + new (target_itr) T(std::move(*original_source_itr)); + original_source_itr->~T(); + ++original_source_itr; + ++target_itr; + } + } + + // Copy-construct new elements. + for (auto *source_itr = insert_begin; source_itr != insert_end; ++source_itr, ++target_itr) + new (target_itr) T(*source_itr); + + // Move over the other half. + if (new_buffer != this->ptr || insert_begin != insert_end) + { + while (original_source_itr != this->end()) + { + new (target_itr) T(std::move(*original_source_itr)); + original_source_itr->~T(); + ++original_source_itr; + ++target_itr; + } + } + + if (this->ptr != stack_storage.data()) + free(this->ptr); + this->ptr = new_buffer; + buffer_capacity = target_capacity; + } + else + { + // Move in place, need to be a bit careful about which elements are constructed and which are not. + // Move the end and construct the new elements. + auto *target_itr = this->end() + count; + auto *source_itr = this->end(); + while (target_itr != this->end() && source_itr != itr) + { + --target_itr; + --source_itr; + new (target_itr) T(std::move(*source_itr)); + } + + // For already constructed elements we can move-assign. + std::move_backward(itr, source_itr, target_itr); + + // For the inserts which go to already constructed elements, we can do a plain copy. + while (itr != this->end() && insert_begin != insert_end) + *itr++ = *insert_begin++; + + // For inserts into newly allocated memory, we must copy-construct instead. + while (insert_begin != insert_end) + { + new (itr) T(*insert_begin); + ++itr; + ++insert_begin; + } + } + + this->buffer_size += count; + } + } + + void insert(T *itr, const T &value) SPIRV_CROSS_NOEXCEPT + { + insert(itr, &value, &value + 1); + } + + T *erase(T *itr) SPIRV_CROSS_NOEXCEPT + { + std::move(itr + 1, this->end(), itr); + this->ptr[--this->buffer_size].~T(); + return itr; + } + + void erase(T *start_erase, T *end_erase) SPIRV_CROSS_NOEXCEPT + { + if (end_erase == this->end()) + { + resize(size_t(start_erase - this->begin())); + } + else + { + auto new_size = this->buffer_size - (end_erase - start_erase); + std::move(end_erase, this->end(), start_erase); + resize(new_size); + } + } + + void resize(size_t new_size) SPIRV_CROSS_NOEXCEPT + { + if (new_size < this->buffer_size) + { + for (size_t i = new_size; i < this->buffer_size; i++) + this->ptr[i].~T(); + } + else if (new_size > this->buffer_size) + { + reserve(new_size); + for (size_t i = this->buffer_size; i < new_size; i++) + new (&this->ptr[i]) T(); + } + + this->buffer_size = new_size; + } + +private: + size_t buffer_capacity = 0; + AlignedBuffer stack_storage; +}; + +// A vector without stack storage. +// Could also be a typedef-ed to std::vector, +// but might as well use the one we have. +template +using Vector = SmallVector; + +#else // SPIRV_CROSS_FORCE_STL_TYPES + +template +using SmallVector = std::vector; +template +using Vector = std::vector; +template +using VectorView = std::vector; + +#endif // SPIRV_CROSS_FORCE_STL_TYPES + +// An object pool which we use for allocating IVariant-derived objects. +// We know we are going to allocate a bunch of objects of each type, +// so amortize the mallocs. +class ObjectPoolBase +{ +public: + virtual ~ObjectPoolBase() = default; + virtual void free_opaque(void *ptr) = 0; +}; + +template +class ObjectPool : public ObjectPoolBase +{ +public: + explicit ObjectPool(unsigned start_object_count_ = 16) + : start_object_count(start_object_count_) + { + } + + template + T *allocate(P &&... p) + { + if (vacants.empty()) + { + unsigned num_objects = start_object_count << memory.size(); + T *ptr = static_cast(malloc(num_objects * sizeof(T))); + if (!ptr) + return nullptr; + + for (unsigned i = 0; i < num_objects; i++) + vacants.push_back(&ptr[i]); + + memory.emplace_back(ptr); + } + + T *ptr = vacants.back(); + vacants.pop_back(); + new (ptr) T(std::forward

(p)...); + return ptr; + } + + void free(T *ptr) + { + ptr->~T(); + vacants.push_back(ptr); + } + + void free_opaque(void *ptr) override + { + free(static_cast(ptr)); + } + + void clear() + { + vacants.clear(); + memory.clear(); + } + +protected: + Vector vacants; + + struct MallocDeleter + { + void operator()(T *ptr) + { + ::free(ptr); + } + }; + + SmallVector> memory; + unsigned start_object_count; +}; + +template +class StringStream +{ +public: + StringStream() + { + reset(); + } + + ~StringStream() + { + reset(); + } + + // Disable copies and moves. Makes it easier to implement, and we don't need it. + StringStream(const StringStream &) = delete; + void operator=(const StringStream &) = delete; + + template ::value, int>::type = 0> + StringStream &operator<<(const T &t) + { + auto s = std::to_string(t); + append(s.data(), s.size()); + return *this; + } + + // Only overload this to make float/double conversions ambiguous. + StringStream &operator<<(uint32_t v) + { + auto s = std::to_string(v); + append(s.data(), s.size()); + return *this; + } + + StringStream &operator<<(char c) + { + append(&c, 1); + return *this; + } + + StringStream &operator<<(const std::string &s) + { + append(s.data(), s.size()); + return *this; + } + + StringStream &operator<<(const char *s) + { + append(s, strlen(s)); + return *this; + } + + template + StringStream &operator<<(const char (&s)[N]) + { + append(s, strlen(s)); + return *this; + } + + std::string str() const + { + std::string ret; + size_t target_size = 0; + for (auto &saved : saved_buffers) + target_size += saved.offset; + target_size += current_buffer.offset; + ret.reserve(target_size); + + for (auto &saved : saved_buffers) + ret.insert(ret.end(), saved.buffer, saved.buffer + saved.offset); + ret.insert(ret.end(), current_buffer.buffer, current_buffer.buffer + current_buffer.offset); + return ret; + } + + void reset() + { + for (auto &saved : saved_buffers) + if (saved.buffer != stack_buffer) + free(saved.buffer); + if (current_buffer.buffer != stack_buffer) + free(current_buffer.buffer); + + saved_buffers.clear(); + current_buffer.buffer = stack_buffer; + current_buffer.offset = 0; + current_buffer.size = sizeof(stack_buffer); + } + +private: + struct Buffer + { + char *buffer = nullptr; + size_t offset = 0; + size_t size = 0; + }; + Buffer current_buffer; + char stack_buffer[StackSize]; + SmallVector saved_buffers; + + void append(const char *s, size_t len) + { + size_t avail = current_buffer.size - current_buffer.offset; + if (avail < len) + { + if (avail > 0) + { + memcpy(current_buffer.buffer + current_buffer.offset, s, avail); + s += avail; + len -= avail; + current_buffer.offset += avail; + } + + saved_buffers.push_back(current_buffer); + size_t target_size = len > BlockSize ? len : BlockSize; + current_buffer.buffer = static_cast(malloc(target_size)); + if (!current_buffer.buffer) + SPIRV_CROSS_THROW("Out of memory."); + + memcpy(current_buffer.buffer, s, len); + current_buffer.offset = len; + current_buffer.size = target_size; + } + else + { + memcpy(current_buffer.buffer + current_buffer.offset, s, len); + current_buffer.offset += len; + } + } +}; + +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_cross_error_handling.hpp b/ios/include/spirv_cross/spirv_cross_error_handling.hpp new file mode 100644 index 00000000..fa90610b --- /dev/null +++ b/ios/include/spirv_cross/spirv_cross_error_handling.hpp @@ -0,0 +1,87 @@ +/* + * Copyright 2015-2020 Arm Limited + * + * 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 SPIRV_CROSS_ERROR_HANDLING +#define SPIRV_CROSS_ERROR_HANDLING + +#include +#include +#include +#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS +#include +#endif + +#ifdef SPIRV_CROSS_NAMESPACE_OVERRIDE +#define SPIRV_CROSS_NAMESPACE SPIRV_CROSS_NAMESPACE_OVERRIDE +#else +#define SPIRV_CROSS_NAMESPACE spirv_cross +#endif + +namespace SPIRV_CROSS_NAMESPACE +{ +#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS +#if !defined(_MSC_VER) || defined(__clang__) +[[noreturn]] +#elif defined(_MSC_VER) +__declspec(noreturn) +#endif +inline void +report_and_abort(const std::string &msg) +{ +#ifdef NDEBUG + (void)msg; +#else + fprintf(stderr, "There was a compiler error: %s\n", msg.c_str()); +#endif + fflush(stderr); + abort(); +} + +#define SPIRV_CROSS_THROW(x) report_and_abort(x) +#else +class CompilerError : public std::runtime_error +{ +public: + explicit CompilerError(const std::string &str) + : std::runtime_error(str) + { + } +}; + +#define SPIRV_CROSS_THROW(x) throw CompilerError(x) +#endif + +// MSVC 2013 does not have noexcept. We need this for Variant to get move constructor to work correctly +// instead of copy constructor. +// MSVC 2013 ignores that move constructors cannot throw in std::vector, so just don't define it. +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define SPIRV_CROSS_NOEXCEPT +#else +#define SPIRV_CROSS_NOEXCEPT noexcept +#endif + +#if __cplusplus >= 201402l +#define SPIRV_CROSS_DEPRECATED(reason) [[deprecated(reason)]] +#elif defined(__GNUC__) +#define SPIRV_CROSS_DEPRECATED(reason) __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define SPIRV_CROSS_DEPRECATED(reason) __declspec(deprecated(reason)) +#else +#define SPIRV_CROSS_DEPRECATED(reason) +#endif +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_cross_parsed_ir.hpp b/ios/include/spirv_cross/spirv_cross_parsed_ir.hpp new file mode 100644 index 00000000..4880c841 --- /dev/null +++ b/ios/include/spirv_cross/spirv_cross_parsed_ir.hpp @@ -0,0 +1,231 @@ +/* + * Copyright 2018-2020 Arm Limited + * + * 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 SPIRV_CROSS_PARSED_IR_HPP +#define SPIRV_CROSS_PARSED_IR_HPP + +#include "spirv_common.hpp" +#include +#include + +namespace SPIRV_CROSS_NAMESPACE +{ + +// This data structure holds all information needed to perform cross-compilation and reflection. +// It is the output of the Parser, but any implementation could create this structure. +// It is intentionally very "open" and struct-like with some helper functions to deal with decorations. +// Parser is the reference implementation of how this data structure should be filled in. + +class ParsedIR +{ +private: + // This must be destroyed after the "ids" vector. + std::unique_ptr pool_group; + +public: + ParsedIR(); + + // Due to custom allocations from object pools, we cannot use a default copy constructor. + ParsedIR(const ParsedIR &other); + ParsedIR &operator=(const ParsedIR &other); + + // Moves are unproblematic, but we need to implement it anyways, since MSVC 2013 does not understand + // how to default-implement these. + ParsedIR(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT; + ParsedIR &operator=(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT; + + // Resizes ids, meta and block_meta. + void set_id_bounds(uint32_t bounds); + + // The raw SPIR-V, instructions and opcodes refer to this by offset + count. + std::vector spirv; + + // Holds various data structures which inherit from IVariant. + SmallVector ids; + + // Various meta data for IDs, decorations, names, etc. + std::unordered_map meta; + + // Holds all IDs which have a certain type. + // This is needed so we can iterate through a specific kind of resource quickly, + // and in-order of module declaration. + SmallVector ids_for_type[TypeCount]; + + // Special purpose lists which contain a union of types. + // This is needed so we can declare specialization constants and structs in an interleaved fashion, + // among other things. + // Constants can be of struct type, and struct array sizes can use specialization constants. + SmallVector ids_for_constant_or_type; + SmallVector ids_for_constant_or_variable; + + // Declared capabilities and extensions in the SPIR-V module. + // Not really used except for reflection at the moment. + SmallVector declared_capabilities; + SmallVector declared_extensions; + + // Meta data about blocks. The cross-compiler needs to query if a block is either of these types. + // It is a bitset as there can be more than one tag per block. + enum BlockMetaFlagBits + { + BLOCK_META_LOOP_HEADER_BIT = 1 << 0, + BLOCK_META_CONTINUE_BIT = 1 << 1, + BLOCK_META_LOOP_MERGE_BIT = 1 << 2, + BLOCK_META_SELECTION_MERGE_BIT = 1 << 3, + BLOCK_META_MULTISELECT_MERGE_BIT = 1 << 4 + }; + using BlockMetaFlags = uint8_t; + SmallVector block_meta; + std::unordered_map continue_block_to_loop_header; + + // Normally, we'd stick SPIREntryPoint in ids array, but it conflicts with SPIRFunction. + // Entry points can therefore be seen as some sort of meta structure. + std::unordered_map entry_points; + FunctionID default_entry_point = 0; + + struct Source + { + uint32_t version = 0; + bool es = false; + bool known = false; + bool hlsl = false; + + Source() = default; + }; + + Source source; + + spv::AddressingModel addressing_model = spv::AddressingModelMax; + spv::MemoryModel memory_model = spv::MemoryModelMax; + + // Decoration handling methods. + // Can be useful for simple "raw" reflection. + // However, most members are here because the Parser needs most of these, + // and might as well just have the whole suite of decoration/name handling in one place. + void set_name(ID id, const std::string &name); + const std::string &get_name(ID id) const; + void set_decoration(ID id, spv::Decoration decoration, uint32_t argument = 0); + void set_decoration_string(ID id, spv::Decoration decoration, const std::string &argument); + bool has_decoration(ID id, spv::Decoration decoration) const; + uint32_t get_decoration(ID id, spv::Decoration decoration) const; + const std::string &get_decoration_string(ID id, spv::Decoration decoration) const; + const Bitset &get_decoration_bitset(ID id) const; + void unset_decoration(ID id, spv::Decoration decoration); + + // Decoration handling methods (for members of a struct). + void set_member_name(TypeID id, uint32_t index, const std::string &name); + const std::string &get_member_name(TypeID id, uint32_t index) const; + void set_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration, uint32_t argument = 0); + void set_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration, + const std::string &argument); + uint32_t get_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const; + const std::string &get_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration) const; + bool has_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const; + const Bitset &get_member_decoration_bitset(TypeID id, uint32_t index) const; + void unset_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration); + + void mark_used_as_array_length(ID id); + uint32_t increase_bound_by(uint32_t count); + Bitset get_buffer_block_flags(const SPIRVariable &var) const; + + void add_typed_id(Types type, ID id); + void remove_typed_id(Types type, ID id); + + class LoopLock + { + public: + explicit LoopLock(uint32_t *counter); + LoopLock(const LoopLock &) = delete; + void operator=(const LoopLock &) = delete; + LoopLock(LoopLock &&other) SPIRV_CROSS_NOEXCEPT; + LoopLock &operator=(LoopLock &&other) SPIRV_CROSS_NOEXCEPT; + ~LoopLock(); + + private: + uint32_t *lock; + }; + + // This must be held while iterating over a type ID array. + // It is undefined if someone calls set<>() while we're iterating over a data structure, so we must + // make sure that this case is avoided. + + // If we have a hard lock, it is an error to call set<>(), and an exception is thrown. + // If we have a soft lock, we silently ignore any additions to the typed arrays. + // This should only be used for physical ID remapping where we need to create an ID, but we will never + // care about iterating over them. + LoopLock create_loop_hard_lock() const; + LoopLock create_loop_soft_lock() const; + + template + void for_each_typed_id(const Op &op) + { + auto loop_lock = create_loop_hard_lock(); + for (auto &id : ids_for_type[T::type]) + { + if (ids[id].get_type() == static_cast(T::type)) + op(id, get(id)); + } + } + + template + void for_each_typed_id(const Op &op) const + { + auto loop_lock = create_loop_hard_lock(); + for (auto &id : ids_for_type[T::type]) + { + if (ids[id].get_type() == static_cast(T::type)) + op(id, get(id)); + } + } + + template + void reset_all_of_type() + { + reset_all_of_type(static_cast(T::type)); + } + + void reset_all_of_type(Types type); + + Meta *find_meta(ID id); + const Meta *find_meta(ID id) const; + + const std::string &get_empty_string() const + { + return empty_string; + } + + void make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set); + +private: + template + T &get(uint32_t id) + { + return variant_get(ids[id]); + } + + template + const T &get(uint32_t id) const + { + return variant_get(ids[id]); + } + + mutable uint32_t loop_iteration_depth_hard = 0; + mutable uint32_t loop_iteration_depth_soft = 0; + std::string empty_string; + Bitset cleared_bitset; +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_cross_util.hpp b/ios/include/spirv_cross/spirv_cross_util.hpp new file mode 100644 index 00000000..708b7cb5 --- /dev/null +++ b/ios/include/spirv_cross/spirv_cross_util.hpp @@ -0,0 +1,30 @@ +/* + * Copyright 2015-2020 Arm Limited + * + * 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 SPIRV_CROSS_UTIL_HPP +#define SPIRV_CROSS_UTIL_HPP + +#include "spirv_cross.hpp" + +namespace spirv_cross_util +{ +void rename_interface_variable(SPIRV_CROSS_NAMESPACE::Compiler &compiler, + const SPIRV_CROSS_NAMESPACE::SmallVector &resources, + uint32_t location, const std::string &name); +void inherit_combined_sampler_bindings(SPIRV_CROSS_NAMESPACE::Compiler &compiler); +} // namespace spirv_cross_util + +#endif diff --git a/ios/include/spirv_cross/spirv_glsl.hpp b/ios/include/spirv_cross/spirv_glsl.hpp new file mode 100644 index 00000000..1eafc2ce --- /dev/null +++ b/ios/include/spirv_cross/spirv_glsl.hpp @@ -0,0 +1,760 @@ +/* + * Copyright 2015-2020 Arm Limited + * + * 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 SPIRV_CROSS_GLSL_HPP +#define SPIRV_CROSS_GLSL_HPP + +#include "GLSL.std.450.h" +#include "spirv_cross.hpp" +#include +#include +#include + +namespace SPIRV_CROSS_NAMESPACE +{ +enum PlsFormat +{ + PlsNone = 0, + + PlsR11FG11FB10F, + PlsR32F, + PlsRG16F, + PlsRGB10A2, + PlsRGBA8, + PlsRG16, + + PlsRGBA8I, + PlsRG16I, + + PlsRGB10A2UI, + PlsRGBA8UI, + PlsRG16UI, + PlsR32UI +}; + +struct PlsRemap +{ + uint32_t id; + PlsFormat format; +}; + +enum AccessChainFlagBits +{ + ACCESS_CHAIN_INDEX_IS_LITERAL_BIT = 1 << 0, + ACCESS_CHAIN_CHAIN_ONLY_BIT = 1 << 1, + ACCESS_CHAIN_PTR_CHAIN_BIT = 1 << 2, + ACCESS_CHAIN_SKIP_REGISTER_EXPRESSION_READ_BIT = 1 << 3, + ACCESS_CHAIN_LITERAL_MSB_FORCE_ID = 1 << 4 +}; +typedef uint32_t AccessChainFlags; + +class CompilerGLSL : public Compiler +{ +public: + struct Options + { + // The shading language version. Corresponds to #version $VALUE. + uint32_t version = 450; + + // Emit the OpenGL ES shading language instead of desktop OpenGL. + bool es = false; + + // Debug option to always emit temporary variables for all expressions. + bool force_temporary = false; + + // If true, Vulkan GLSL features are used instead of GL-compatible features. + // Mostly useful for debugging SPIR-V files. + bool vulkan_semantics = false; + + // If true, gl_PerVertex is explicitly redeclared in vertex, geometry and tessellation shaders. + // The members of gl_PerVertex is determined by which built-ins are declared by the shader. + // This option is ignored in ES versions, as redeclaration in ES is not required, and it depends on a different extension + // (EXT_shader_io_blocks) which makes things a bit more fuzzy. + bool separate_shader_objects = false; + + // Flattens multidimensional arrays, e.g. float foo[a][b][c] into single-dimensional arrays, + // e.g. float foo[a * b * c]. + // This function does not change the actual SPIRType of any object. + // Only the generated code, including declarations of interface variables are changed to be single array dimension. + bool flatten_multidimensional_arrays = false; + + // For older desktop GLSL targets than version 420, the + // GL_ARB_shading_language_420pack extensions is used to be able to support + // layout(binding) on UBOs and samplers. + // If disabled on older targets, binding decorations will be stripped. + bool enable_420pack_extension = true; + + // In non-Vulkan GLSL, emit push constant blocks as UBOs rather than plain uniforms. + bool emit_push_constant_as_uniform_buffer = false; + + // Always emit uniform blocks as plain uniforms, regardless of the GLSL version, even when UBOs are supported. + // Does not apply to shader storage or push constant blocks. + bool emit_uniform_buffer_as_plain_uniforms = false; + + // Emit OpLine directives if present in the module. + // May not correspond exactly to original source, but should be a good approximation. + bool emit_line_directives = false; + + // In cases where readonly/writeonly decoration are not used at all, + // we try to deduce which qualifier(s) we should actually used, since actually emitting + // read-write decoration is very rare, and older glslang/HLSL compilers tend to just emit readwrite as a matter of fact. + // The default (true) is to enable automatic deduction for these cases, but if you trust the decorations set + // by the SPIR-V, it's recommended to set this to false. + bool enable_storage_image_qualifier_deduction = true; + + // On some targets (WebGPU), uninitialized variables are banned. + // If this is enabled, all variables (temporaries, Private, Function) + // which would otherwise be uninitialized will now be initialized to 0 instead. + bool force_zero_initialized_variables = false; + + enum Precision + { + DontCare, + Lowp, + Mediump, + Highp + }; + + struct + { + // GLSL: In vertex shaders, rewrite [0, w] depth (Vulkan/D3D style) to [-w, w] depth (GL style). + // MSL: In vertex shaders, rewrite [-w, w] depth (GL style) to [0, w] depth. + // HLSL: In vertex shaders, rewrite [-w, w] depth (GL style) to [0, w] depth. + bool fixup_clipspace = false; + + // Inverts gl_Position.y or equivalent. + bool flip_vert_y = false; + + // GLSL only, for HLSL version of this option, see CompilerHLSL. + // If true, the backend will assume that InstanceIndex will need to apply + // a base instance offset. Set to false if you know you will never use base instance + // functionality as it might remove some internal uniforms. + bool support_nonzero_base_instance = true; + } vertex; + + struct + { + // Add precision mediump float in ES targets when emitting GLES source. + // Add precision highp int in ES targets when emitting GLES source. + Precision default_float_precision = Mediump; + Precision default_int_precision = Highp; + } fragment; + }; + + void remap_pixel_local_storage(std::vector inputs, std::vector outputs) + { + pls_inputs = std::move(inputs); + pls_outputs = std::move(outputs); + remap_pls_variables(); + } + + // Redirect a subpassInput reading from input_attachment_index to instead load its value from + // the color attachment at location = color_location. Requires ESSL. + void remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location); + + explicit CompilerGLSL(std::vector spirv_) + : Compiler(std::move(spirv_)) + { + init(); + } + + CompilerGLSL(const uint32_t *ir_, size_t word_count) + : Compiler(ir_, word_count) + { + init(); + } + + explicit CompilerGLSL(const ParsedIR &ir_) + : Compiler(ir_) + { + init(); + } + + explicit CompilerGLSL(ParsedIR &&ir_) + : Compiler(std::move(ir_)) + { + init(); + } + + const Options &get_common_options() const + { + return options; + } + + void set_common_options(const Options &opts) + { + options = opts; + } + + std::string compile() override; + + // Returns the current string held in the conversion buffer. Useful for + // capturing what has been converted so far when compile() throws an error. + std::string get_partial_source(); + + // Adds a line to be added right after #version in GLSL backend. + // This is useful for enabling custom extensions which are outside the scope of SPIRV-Cross. + // This can be combined with variable remapping. + // A new-line will be added. + // + // While add_header_line() is a more generic way of adding arbitrary text to the header + // of a GLSL file, require_extension() should be used when adding extensions since it will + // avoid creating collisions with SPIRV-Cross generated extensions. + // + // Code added via add_header_line() is typically backend-specific. + void add_header_line(const std::string &str); + + // Adds an extension which is required to run this shader, e.g. + // require_extension("GL_KHR_my_extension"); + void require_extension(const std::string &ext); + + // Legacy GLSL compatibility method. + // Takes a uniform or push constant variable and flattens it into a (i|u)vec4 array[N]; array instead. + // For this to work, all types in the block must be the same basic type, e.g. mixing vec2 and vec4 is fine, but + // mixing int and float is not. + // The name of the uniform array will be the same as the interface block name. + void flatten_buffer_block(VariableID id); + + // After compilation, query if a variable ID was used as a depth resource. + // This is meaningful for MSL since descriptor types depend on this knowledge. + // Cases which return true: + // - Images which are declared with depth = 1 image type. + // - Samplers which are statically used at least once with Dref opcodes. + // - Images which are statically used at least once with Dref opcodes. + bool variable_is_depth_or_compare(VariableID id) const; + +protected: + void reset(); + void emit_function(SPIRFunction &func, const Bitset &return_flags); + + bool has_extension(const std::string &ext) const; + void require_extension_internal(const std::string &ext); + + // Virtualize methods which need to be overridden by subclass targets like C++ and such. + virtual void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags); + + SPIRBlock *current_emitting_block = nullptr; + SPIRBlock *current_emitting_switch = nullptr; + bool current_emitting_switch_fallthrough = false; + + virtual void emit_instruction(const Instruction &instr); + void emit_block_instructions(SPIRBlock &block); + virtual void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, + uint32_t count); + virtual void emit_spv_amd_shader_ballot_op(uint32_t result_type, uint32_t result_id, uint32_t op, + const uint32_t *args, uint32_t count); + virtual void emit_spv_amd_shader_explicit_vertex_parameter_op(uint32_t result_type, uint32_t result_id, uint32_t op, + const uint32_t *args, uint32_t count); + virtual void emit_spv_amd_shader_trinary_minmax_op(uint32_t result_type, uint32_t result_id, uint32_t op, + const uint32_t *args, uint32_t count); + virtual void emit_spv_amd_gcn_shader_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, + uint32_t count); + virtual void emit_header(); + void emit_line_directive(uint32_t file_id, uint32_t line_literal); + void build_workgroup_size(SmallVector &arguments, const SpecializationConstant &x, + const SpecializationConstant &y, const SpecializationConstant &z); + + virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id); + virtual void emit_texture_op(const Instruction &i); + virtual std::string to_texture_op(const Instruction &i, bool *forward, + SmallVector &inherited_expressions); + virtual void emit_subgroup_op(const Instruction &i); + virtual std::string type_to_glsl(const SPIRType &type, uint32_t id = 0); + virtual std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage); + virtual void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, + const std::string &qualifier = "", uint32_t base_offset = 0); + virtual void emit_struct_padding_target(const SPIRType &type); + virtual std::string image_type_glsl(const SPIRType &type, uint32_t id = 0); + std::string constant_expression(const SPIRConstant &c); + std::string constant_op_expression(const SPIRConstantOp &cop); + virtual std::string constant_expression_vector(const SPIRConstant &c, uint32_t vector); + virtual void emit_fixup(); + virtual std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0); + virtual std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id); + virtual std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, + bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, + bool has_dref, uint32_t lod, uint32_t minlod); + virtual std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, + bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref, + uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, + uint32_t offset, uint32_t bias, uint32_t comp, uint32_t sample, + uint32_t minlod, bool *p_forward); + virtual void emit_buffer_block(const SPIRVariable &type); + virtual void emit_push_constant_block(const SPIRVariable &var); + virtual void emit_uniform(const SPIRVariable &var); + virtual std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t physical_type_id, + bool packed_type, bool row_major); + + virtual bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const; + + void emit_copy_logical_type(uint32_t lhs_id, uint32_t lhs_type_id, uint32_t rhs_id, uint32_t rhs_type_id, + SmallVector chain); + + StringStream<> buffer; + + template + inline void statement_inner(T &&t) + { + buffer << std::forward(t); + statement_count++; + } + + template + inline void statement_inner(T &&t, Ts &&... ts) + { + buffer << std::forward(t); + statement_count++; + statement_inner(std::forward(ts)...); + } + + template + inline void statement(Ts &&... ts) + { + if (is_forcing_recompilation()) + { + // Do not bother emitting code while force_recompile is active. + // We will compile again. + statement_count++; + return; + } + + if (redirect_statement) + { + redirect_statement->push_back(join(std::forward(ts)...)); + statement_count++; + } + else + { + for (uint32_t i = 0; i < indent; i++) + buffer << " "; + statement_inner(std::forward(ts)...); + buffer << '\n'; + } + } + + template + inline void statement_no_indent(Ts &&... ts) + { + auto old_indent = indent; + indent = 0; + statement(std::forward(ts)...); + indent = old_indent; + } + + // Used for implementing continue blocks where + // we want to obtain a list of statements we can merge + // on a single line separated by comma. + SmallVector *redirect_statement = nullptr; + const SPIRBlock *current_continue_block = nullptr; + + void begin_scope(); + void end_scope(); + void end_scope(const std::string &trailer); + void end_scope_decl(); + void end_scope_decl(const std::string &decl); + + Options options; + + virtual std::string type_to_array_glsl( + const SPIRType &type); // Allow Metal to use the array template to make arrays a value type + std::string to_array_size(const SPIRType &type, uint32_t index); + uint32_t to_array_size_literal(const SPIRType &type, uint32_t index) const; + uint32_t to_array_size_literal(const SPIRType &type) const; + virtual std::string variable_decl(const SPIRVariable &variable); // Threadgroup arrays can't have a wrapper type + std::string variable_decl_function_local(SPIRVariable &variable); + + void add_local_variable_name(uint32_t id); + void add_resource_name(uint32_t id); + void add_member_name(SPIRType &type, uint32_t name); + void add_function_overload(const SPIRFunction &func); + + virtual bool is_non_native_row_major_matrix(uint32_t id); + virtual bool member_is_non_native_row_major_matrix(const SPIRType &type, uint32_t index); + bool member_is_remapped_physical_type(const SPIRType &type, uint32_t index) const; + bool member_is_packed_physical_type(const SPIRType &type, uint32_t index) const; + virtual std::string convert_row_major_matrix(std::string exp_str, const SPIRType &exp_type, + uint32_t physical_type_id, bool is_packed); + + std::unordered_set local_variable_names; + std::unordered_set resource_names; + std::unordered_set block_input_names; + std::unordered_set block_output_names; + std::unordered_set block_ubo_names; + std::unordered_set block_ssbo_names; + std::unordered_set block_names; // A union of all block_*_names. + std::unordered_map> function_overloads; + std::unordered_map preserved_aliases; + void preserve_alias_on_reset(uint32_t id); + void reset_name_caches(); + + bool processing_entry_point = false; + + // Can be overriden by subclass backends for trivial things which + // shouldn't need polymorphism. + struct BackendVariations + { + std::string discard_literal = "discard"; + std::string demote_literal = "demote"; + std::string null_pointer_literal = ""; + bool float_literal_suffix = false; + bool double_literal_suffix = true; + bool uint32_t_literal_suffix = true; + bool long_long_literal_suffix = false; + const char *basic_int_type = "int"; + const char *basic_uint_type = "uint"; + const char *basic_int8_type = "int8_t"; + const char *basic_uint8_type = "uint8_t"; + const char *basic_int16_type = "int16_t"; + const char *basic_uint16_type = "uint16_t"; + const char *int16_t_literal_suffix = "s"; + const char *uint16_t_literal_suffix = "us"; + const char *nonuniform_qualifier = "nonuniformEXT"; + const char *boolean_mix_function = "mix"; + bool swizzle_is_function = false; + bool shared_is_implied = false; + bool unsized_array_supported = true; + bool explicit_struct_type = false; + bool use_initializer_list = false; + bool use_typed_initializer_list = false; + bool can_declare_struct_inline = true; + bool can_declare_arrays_inline = true; + bool native_row_major_matrix = true; + bool use_constructor_splatting = true; + bool allow_precision_qualifiers = false; + bool can_swizzle_scalar = false; + bool force_gl_in_out_block = false; + bool can_return_array = true; + bool allow_truncated_access_chain = false; + bool supports_extensions = false; + bool supports_empty_struct = false; + bool array_is_value_type = true; + bool comparison_image_samples_scalar = false; + bool native_pointers = false; + bool support_small_type_sampling_result = false; + bool support_case_fallthrough = true; + bool use_array_constructor = false; + } backend; + + void emit_struct(SPIRType &type); + void emit_resources(); + void emit_buffer_block_native(const SPIRVariable &var); + void emit_buffer_reference_block(SPIRType &type, bool forward_declaration); + void emit_buffer_block_legacy(const SPIRVariable &var); + void emit_buffer_block_flattened(const SPIRVariable &type); + void emit_declared_builtin_block(spv::StorageClass storage, spv::ExecutionModel model); + bool should_force_emit_builtin_block(spv::StorageClass storage); + void emit_push_constant_block_vulkan(const SPIRVariable &var); + void emit_push_constant_block_glsl(const SPIRVariable &var); + void emit_interface_block(const SPIRVariable &type); + void emit_flattened_io_block(const SPIRVariable &var, const char *qual); + void emit_block_chain(SPIRBlock &block); + void emit_hoisted_temporaries(SmallVector> &temporaries); + std::string constant_value_macro_name(uint32_t id); + void emit_constant(const SPIRConstant &constant); + void emit_specialization_constant_op(const SPIRConstantOp &constant); + std::string emit_continue_block(uint32_t continue_block, bool follow_true_block, bool follow_false_block); + bool attempt_emit_loop_header(SPIRBlock &block, SPIRBlock::Method method); + + void branch(BlockID from, BlockID to); + void branch_to_continue(BlockID from, BlockID to); + void branch(BlockID from, uint32_t cond, BlockID true_block, BlockID false_block); + void flush_phi(BlockID from, BlockID to); + void flush_variable_declaration(uint32_t id); + void flush_undeclared_variables(SPIRBlock &block); + void emit_variable_temporary_copies(const SPIRVariable &var); + + bool should_dereference(uint32_t id); + bool should_forward(uint32_t id) const; + bool should_suppress_usage_tracking(uint32_t id) const; + void emit_mix_op(uint32_t result_type, uint32_t id, uint32_t left, uint32_t right, uint32_t lerp); + void emit_nminmax_op(uint32_t result_type, uint32_t id, uint32_t op0, uint32_t op1, GLSLstd450 op); + bool to_trivial_mix_op(const SPIRType &type, std::string &op, uint32_t left, uint32_t right, uint32_t lerp); + void emit_quaternary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, + uint32_t op3, const char *op); + void emit_trinary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, + const char *op); + void emit_binary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op); + + void emit_unary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op, + SPIRType::BaseType input_type, SPIRType::BaseType expected_result_type); + void emit_binary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op, + SPIRType::BaseType input_type, bool skip_cast_if_equal_type); + void emit_binary_func_op_cast_clustered(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, + const char *op, SPIRType::BaseType input_type); + void emit_trinary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, + const char *op, SPIRType::BaseType input_type); + void emit_trinary_func_op_bitextract(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, + uint32_t op2, const char *op, SPIRType::BaseType expected_result_type, + SPIRType::BaseType input_type0, SPIRType::BaseType input_type1, + SPIRType::BaseType input_type2); + void emit_bitfield_insert_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, + uint32_t op3, const char *op, SPIRType::BaseType offset_count_type); + + void emit_unary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op); + void emit_unrolled_unary_op(uint32_t result_type, uint32_t result_id, uint32_t operand, const char *op); + void emit_binary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op); + void emit_unrolled_binary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op, + bool negate, SPIRType::BaseType expected_type); + void emit_binary_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op, + SPIRType::BaseType input_type, bool skip_cast_if_equal_type); + + SPIRType binary_op_bitcast_helper(std::string &cast_op0, std::string &cast_op1, SPIRType::BaseType &input_type, + uint32_t op0, uint32_t op1, bool skip_cast_if_equal_type); + + virtual bool emit_complex_bitcast(uint32_t result_type, uint32_t id, uint32_t op0); + + std::string to_ternary_expression(const SPIRType &result_type, uint32_t select, uint32_t true_value, + uint32_t false_value); + + void emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op); + bool expression_is_forwarded(uint32_t id) const; + bool expression_suppresses_usage_tracking(uint32_t id) const; + SPIRExpression &emit_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs, + bool suppress_usage_tracking = false); + + void access_chain_internal_append_index(std::string &expr, uint32_t base, const SPIRType *type, + AccessChainFlags flags, bool &access_chain_is_arrayed, uint32_t index); + + std::string access_chain_internal(uint32_t base, const uint32_t *indices, uint32_t count, AccessChainFlags flags, + AccessChainMeta *meta); + + std::string access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, + AccessChainMeta *meta = nullptr, bool ptr_chain = false); + + std::string flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count, + const SPIRType &target_type, uint32_t offset, uint32_t matrix_stride, + uint32_t array_stride, bool need_transpose); + std::string flattened_access_chain_struct(uint32_t base, const uint32_t *indices, uint32_t count, + const SPIRType &target_type, uint32_t offset); + std::string flattened_access_chain_matrix(uint32_t base, const uint32_t *indices, uint32_t count, + const SPIRType &target_type, uint32_t offset, uint32_t matrix_stride, + bool need_transpose); + std::string flattened_access_chain_vector(uint32_t base, const uint32_t *indices, uint32_t count, + const SPIRType &target_type, uint32_t offset, uint32_t matrix_stride, + bool need_transpose); + std::pair flattened_access_chain_offset(const SPIRType &basetype, const uint32_t *indices, + uint32_t count, uint32_t offset, + uint32_t word_stride, bool *need_transpose = nullptr, + uint32_t *matrix_stride = nullptr, + uint32_t *array_stride = nullptr, + bool ptr_chain = false); + + const char *index_to_swizzle(uint32_t index); + std::string remap_swizzle(const SPIRType &result_type, uint32_t input_components, const std::string &expr); + std::string declare_temporary(uint32_t type, uint32_t id); + void emit_uninitialized_temporary(uint32_t type, uint32_t id); + SPIRExpression &emit_uninitialized_temporary_expression(uint32_t type, uint32_t id); + void append_global_func_args(const SPIRFunction &func, uint32_t index, SmallVector &arglist); + std::string to_expression(uint32_t id, bool register_expression_read = true); + std::string to_composite_constructor_expression(uint32_t id); + std::string to_rerolled_array_expression(const std::string &expr, const SPIRType &type); + std::string to_enclosed_expression(uint32_t id, bool register_expression_read = true); + std::string to_unpacked_expression(uint32_t id, bool register_expression_read = true); + std::string to_unpacked_row_major_matrix_expression(uint32_t id); + std::string to_enclosed_unpacked_expression(uint32_t id, bool register_expression_read = true); + std::string to_dereferenced_expression(uint32_t id, bool register_expression_read = true); + std::string to_pointer_expression(uint32_t id, bool register_expression_read = true); + std::string to_enclosed_pointer_expression(uint32_t id, bool register_expression_read = true); + std::string to_extract_component_expression(uint32_t id, uint32_t index); + std::string enclose_expression(const std::string &expr); + std::string dereference_expression(const SPIRType &expression_type, const std::string &expr); + std::string address_of_expression(const std::string &expr); + void strip_enclosed_expression(std::string &expr); + std::string to_member_name(const SPIRType &type, uint32_t index); + virtual std::string to_member_reference(uint32_t base, const SPIRType &type, uint32_t index, bool ptr_chain); + std::string type_to_glsl_constructor(const SPIRType &type); + std::string argument_decl(const SPIRFunction::Parameter &arg); + virtual std::string to_qualifiers_glsl(uint32_t id); + const char *to_precision_qualifiers_glsl(uint32_t id); + virtual const char *to_storage_qualifiers_glsl(const SPIRVariable &var); + const char *flags_to_qualifiers_glsl(const SPIRType &type, const Bitset &flags); + const char *format_to_glsl(spv::ImageFormat format); + virtual std::string layout_for_member(const SPIRType &type, uint32_t index); + virtual std::string to_interpolation_qualifiers(const Bitset &flags); + std::string layout_for_variable(const SPIRVariable &variable); + std::string to_combined_image_sampler(VariableID image_id, VariableID samp_id); + virtual bool skip_argument(uint32_t id) const; + virtual void emit_array_copy(const std::string &lhs, uint32_t rhs_id, spv::StorageClass lhs_storage, + spv::StorageClass rhs_storage); + virtual void emit_block_hints(const SPIRBlock &block); + virtual std::string to_initializer_expression(const SPIRVariable &var); + virtual std::string to_zero_initialized_expression(uint32_t type_id); + bool type_can_zero_initialize(const SPIRType &type) const; + + bool buffer_is_packing_standard(const SPIRType &type, BufferPackingStandard packing, + uint32_t *failed_index = nullptr, uint32_t start_offset = 0, + uint32_t end_offset = ~(0u)); + std::string buffer_to_packing_standard(const SPIRType &type, bool support_std430_without_scalar_layout); + + uint32_t type_to_packed_base_size(const SPIRType &type, BufferPackingStandard packing); + uint32_t type_to_packed_alignment(const SPIRType &type, const Bitset &flags, BufferPackingStandard packing); + uint32_t type_to_packed_array_stride(const SPIRType &type, const Bitset &flags, BufferPackingStandard packing); + uint32_t type_to_packed_size(const SPIRType &type, const Bitset &flags, BufferPackingStandard packing); + + std::string bitcast_glsl(const SPIRType &result_type, uint32_t arg); + virtual std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type); + + std::string bitcast_expression(SPIRType::BaseType target_type, uint32_t arg); + std::string bitcast_expression(const SPIRType &target_type, SPIRType::BaseType expr_type, const std::string &expr); + + std::string build_composite_combiner(uint32_t result_type, const uint32_t *elems, uint32_t length); + bool remove_duplicate_swizzle(std::string &op); + bool remove_unity_swizzle(uint32_t base, std::string &op); + + // Can modify flags to remote readonly/writeonly if image type + // and force recompile. + bool check_atomic_image(uint32_t id); + + virtual void replace_illegal_names(); + void replace_illegal_names(const std::unordered_set &keywords); + virtual void emit_entry_point_declarations(); + + void replace_fragment_output(SPIRVariable &var); + void replace_fragment_outputs(); + bool check_explicit_lod_allowed(uint32_t lod); + std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t id); + + uint32_t indent = 0; + + std::unordered_set emitted_functions; + + // Ensure that we declare phi-variable copies even if the original declaration isn't deferred + std::unordered_set flushed_phi_variables; + + std::unordered_set flattened_buffer_blocks; + std::unordered_set flattened_structs; + + std::string load_flattened_struct(SPIRVariable &var); + std::string to_flattened_struct_member(const SPIRVariable &var, uint32_t index); + void store_flattened_struct(SPIRVariable &var, uint32_t value); + + // Usage tracking. If a temporary is used more than once, use the temporary instead to + // avoid AST explosion when SPIRV is generated with pure SSA and doesn't write stuff to variables. + std::unordered_map expression_usage_counts; + void track_expression_read(uint32_t id); + + SmallVector forced_extensions; + SmallVector header_lines; + + // Used when expressions emit extra opcodes with their own unique IDs, + // and we need to reuse the IDs across recompilation loops. + // Currently used by NMin/Max/Clamp implementations. + std::unordered_map extra_sub_expressions; + + uint32_t statement_count = 0; + + inline bool is_legacy() const + { + return (options.es && options.version < 300) || (!options.es && options.version < 130); + } + + inline bool is_legacy_es() const + { + return options.es && options.version < 300; + } + + inline bool is_legacy_desktop() const + { + return !options.es && options.version < 130; + } + + bool args_will_forward(uint32_t id, const uint32_t *args, uint32_t num_args, bool pure); + void register_call_out_argument(uint32_t id); + void register_impure_function_call(); + void register_control_dependent_expression(uint32_t expr); + + // GL_EXT_shader_pixel_local_storage support. + std::vector pls_inputs; + std::vector pls_outputs; + std::string pls_decl(const PlsRemap &variable); + const char *to_pls_qualifiers_glsl(const SPIRVariable &variable); + void emit_pls(); + void remap_pls_variables(); + + // GL_EXT_shader_framebuffer_fetch support. + std::vector> subpass_to_framebuffer_fetch_attachment; + std::unordered_set inout_color_attachments; + bool subpass_input_is_framebuffer_fetch(uint32_t id) const; + void emit_inout_fragment_outputs_copy_to_subpass_inputs(); + const SPIRVariable *find_subpass_input_by_attachment_index(uint32_t index) const; + const SPIRVariable *find_color_output_by_location(uint32_t location) const; + + // A variant which takes two sets of name. The secondary is only used to verify there are no collisions, + // but the set is not updated when we have found a new name. + // Used primarily when adding block interface names. + void add_variable(std::unordered_set &variables_primary, + const std::unordered_set &variables_secondary, std::string &name); + + void check_function_call_constraints(const uint32_t *args, uint32_t length); + void handle_invalid_expression(uint32_t id); + void find_static_extensions(); + + std::string emit_for_loop_initializers(const SPIRBlock &block); + void emit_while_loop_initializers(const SPIRBlock &block); + bool for_loop_initializers_are_same_type(const SPIRBlock &block); + bool optimize_read_modify_write(const SPIRType &type, const std::string &lhs, const std::string &rhs); + void fixup_image_load_store_access(); + + bool type_is_empty(const SPIRType &type); + + virtual void declare_undefined_values(); + + static std::string sanitize_underscores(const std::string &str); + + bool can_use_io_location(spv::StorageClass storage, bool block); + const Instruction *get_next_instruction_in_block(const Instruction &instr); + static uint32_t mask_relevant_memory_semantics(uint32_t semantics); + + std::string convert_half_to_string(const SPIRConstant &value, uint32_t col, uint32_t row); + std::string convert_float_to_string(const SPIRConstant &value, uint32_t col, uint32_t row); + std::string convert_double_to_string(const SPIRConstant &value, uint32_t col, uint32_t row); + + std::string convert_separate_image_to_expression(uint32_t id); + + // Builtins in GLSL are always specific signedness, but the SPIR-V can declare them + // as either unsigned or signed. + // Sometimes we will need to automatically perform bitcasts on load and store to make this work. + virtual void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type); + virtual void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type); + void unroll_array_from_complex_load(uint32_t target_id, uint32_t source_id, std::string &expr); + void convert_non_uniform_expression(const SPIRType &type, std::string &expr); + + void handle_store_to_invariant_variable(uint32_t store_id, uint32_t value_id); + void disallow_forwarding_in_expression_chain(const SPIRExpression &expr); + + bool expression_is_constant_null(uint32_t id) const; + virtual void emit_store_statement(uint32_t lhs_expression, uint32_t rhs_expression); + + uint32_t get_integer_width_for_instruction(const Instruction &instr) const; + uint32_t get_integer_width_for_glsl_instruction(GLSLstd450 op, const uint32_t *arguments, uint32_t length) const; + + bool variable_is_lut(const SPIRVariable &var) const; + + char current_locale_radix_character = '.'; + + void fixup_type_alias(); + void reorder_type_alias(); + + void propagate_nonuniform_qualifier(uint32_t id); + + static const char *vector_swizzle(int vecsize, int index); + +private: + void init(); +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_hlsl.hpp b/ios/include/spirv_cross/spirv_hlsl.hpp new file mode 100644 index 00000000..e98c6443 --- /dev/null +++ b/ios/include/spirv_cross/spirv_hlsl.hpp @@ -0,0 +1,329 @@ +/* + * Copyright 2016-2020 Robert Konrad + * + * 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 SPIRV_HLSL_HPP +#define SPIRV_HLSL_HPP + +#include "spirv_glsl.hpp" +#include + +namespace SPIRV_CROSS_NAMESPACE +{ +// Interface which remaps vertex inputs to a fixed semantic name to make linking easier. +struct HLSLVertexAttributeRemap +{ + uint32_t location; + std::string semantic; +}; +// Specifying a root constant (d3d12) or push constant range (vulkan). +// +// `start` and `end` denotes the range of the root constant in bytes. +// Both values need to be multiple of 4. +struct RootConstants +{ + uint32_t start; + uint32_t end; + + uint32_t binding; + uint32_t space; +}; + +// For finer control, decorations may be removed from specific resources instead with unset_decoration(). +enum HLSLBindingFlagBits +{ + HLSL_BINDING_AUTO_NONE_BIT = 0, + + // Push constant (root constant) resources will be declared as CBVs (b-space) without a register() declaration. + // A register will be automatically assigned by the D3D compiler, but must therefore be reflected in D3D-land. + // Push constants do not normally have a DecorationBinding set, but if they do, this can be used to ignore it. + HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT = 1 << 0, + + // cbuffer resources will be declared as CBVs (b-space) without a register() declaration. + // A register will be automatically assigned, but must be reflected in D3D-land. + HLSL_BINDING_AUTO_CBV_BIT = 1 << 1, + + // All SRVs (t-space) will be declared without a register() declaration. + HLSL_BINDING_AUTO_SRV_BIT = 1 << 2, + + // All UAVs (u-space) will be declared without a register() declaration. + HLSL_BINDING_AUTO_UAV_BIT = 1 << 3, + + // All samplers (s-space) will be declared without a register() declaration. + HLSL_BINDING_AUTO_SAMPLER_BIT = 1 << 4, + + // No resources will be declared with register(). + HLSL_BINDING_AUTO_ALL = 0x7fffffff +}; +using HLSLBindingFlags = uint32_t; + +// By matching stage, desc_set and binding for a SPIR-V resource, +// register bindings are set based on whether the HLSL resource is a +// CBV, UAV, SRV or Sampler. A single binding in SPIR-V might contain multiple +// resource types, e.g. COMBINED_IMAGE_SAMPLER, and SRV/Sampler bindings will be used respectively. +// On SM 5.0 and lower, register_space is ignored. +// +// To remap a push constant block which does not have any desc_set/binding associated with it, +// use ResourceBindingPushConstant{DescriptorSet,Binding} as values for desc_set/binding. +// For deeper control of push constants, set_root_constant_layouts() can be used instead. +struct HLSLResourceBinding +{ + spv::ExecutionModel stage = spv::ExecutionModelMax; + uint32_t desc_set = 0; + uint32_t binding = 0; + + struct Binding + { + uint32_t register_space = 0; + uint32_t register_binding = 0; + } cbv, uav, srv, sampler; +}; + +class CompilerHLSL : public CompilerGLSL +{ +public: + struct Options + { + uint32_t shader_model = 30; // TODO: map ps_4_0_level_9_0,... somehow + + // Allows the PointSize builtin, and ignores it, as PointSize is not supported in HLSL. + bool point_size_compat = false; + + // Allows the PointCoord builtin, returns float2(0.5, 0.5), as PointCoord is not supported in HLSL. + bool point_coord_compat = false; + + // If true, the backend will assume that VertexIndex and InstanceIndex will need to apply + // a base offset, and you will need to fill in a cbuffer with offsets. + // Set to false if you know you will never use base instance or base vertex + // functionality as it might remove an internal cbuffer. + bool support_nonzero_base_vertex_base_instance = false; + + // Forces a storage buffer to always be declared as UAV, even if the readonly decoration is used. + // By default, a readonly storage buffer will be declared as ByteAddressBuffer (SRV) instead. + bool force_storage_buffer_as_uav = false; + + // Forces any storage image type marked as NonWritable to be considered an SRV instead. + // For this to work with function call parameters, NonWritable must be considered to be part of the type system + // so that NonWritable image arguments are also translated to Texture rather than RWTexture. + bool nonwritable_uav_texture_as_srv = false; + }; + + explicit CompilerHLSL(std::vector spirv_) + : CompilerGLSL(std::move(spirv_)) + { + } + + CompilerHLSL(const uint32_t *ir_, size_t size) + : CompilerGLSL(ir_, size) + { + } + + explicit CompilerHLSL(const ParsedIR &ir_) + : CompilerGLSL(ir_) + { + } + + explicit CompilerHLSL(ParsedIR &&ir_) + : CompilerGLSL(std::move(ir_)) + { + } + + const Options &get_hlsl_options() const + { + return hlsl_options; + } + + void set_hlsl_options(const Options &opts) + { + hlsl_options = opts; + } + + // Optionally specify a custom root constant layout. + // + // Push constants ranges will be split up according to the + // layout specified. + void set_root_constant_layouts(std::vector layout); + + // Compiles and remaps vertex attributes at specific locations to a fixed semantic. + // The default is TEXCOORD# where # denotes location. + // Matrices are unrolled to vectors with notation ${SEMANTIC}_#, where # denotes row. + // $SEMANTIC is either TEXCOORD# or a semantic name specified here. + void add_vertex_attribute_remap(const HLSLVertexAttributeRemap &vertex_attributes); + std::string compile() override; + + // This is a special HLSL workaround for the NumWorkGroups builtin. + // This does not exist in HLSL, so the calling application must create a dummy cbuffer in + // which the application will store this builtin. + // The cbuffer layout will be: + // cbuffer SPIRV_Cross_NumWorkgroups : register(b#, space#) { uint3 SPIRV_Cross_NumWorkgroups_count; }; + // This must be called before compile(). + // The function returns 0 if NumWorkGroups builtin is not statically used in the shader from the current entry point. + // If non-zero, this returns the variable ID of a cbuffer which corresponds to + // the cbuffer declared above. By default, no binding or descriptor set decoration is set, + // so the calling application should declare explicit bindings on this ID before calling compile(). + VariableID remap_num_workgroups_builtin(); + + // Controls how resource bindings are declared in the output HLSL. + void set_resource_binding_flags(HLSLBindingFlags flags); + + // resource is a resource binding to indicate the HLSL CBV, SRV, UAV or sampler binding + // to use for a particular SPIR-V description set + // and binding. If resource bindings are provided, + // is_hlsl_resource_binding_used() will return true after calling ::compile() if + // the set/binding combination was used by the HLSL code. + void add_hlsl_resource_binding(const HLSLResourceBinding &resource); + bool is_hlsl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding) const; + +private: + std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override; + std::string image_type_hlsl(const SPIRType &type, uint32_t id); + std::string image_type_hlsl_modern(const SPIRType &type, uint32_t id); + std::string image_type_hlsl_legacy(const SPIRType &type, uint32_t id); + void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override; + void emit_hlsl_entry_point(); + void emit_header() override; + void emit_resources(); + void declare_undefined_values() override; + void emit_interface_block_globally(const SPIRVariable &type); + void emit_interface_block_in_struct(const SPIRVariable &type, std::unordered_set &active_locations); + void emit_builtin_inputs_in_struct(); + void emit_builtin_outputs_in_struct(); + void emit_texture_op(const Instruction &i) override; + void emit_instruction(const Instruction &instruction) override; + void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, + uint32_t count) override; + void emit_buffer_block(const SPIRVariable &type) override; + void emit_push_constant_block(const SPIRVariable &var) override; + void emit_uniform(const SPIRVariable &var) override; + void emit_modern_uniform(const SPIRVariable &var); + void emit_legacy_uniform(const SPIRVariable &var); + void emit_specialization_constants_and_structs(); + void emit_composite_constants(); + void emit_fixup() override; + std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override; + std::string layout_for_member(const SPIRType &type, uint32_t index) override; + std::string to_interpolation_qualifiers(const Bitset &flags) override; + std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override; + bool emit_complex_bitcast(uint32_t result_type, uint32_t id, uint32_t op0) override; + std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override; + std::string to_sampler_expression(uint32_t id); + std::string to_resource_binding(const SPIRVariable &var); + std::string to_resource_binding_sampler(const SPIRVariable &var); + std::string to_resource_register(HLSLBindingFlagBits flag, char space, uint32_t binding, uint32_t set); + void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override; + void emit_access_chain(const Instruction &instruction); + void emit_load(const Instruction &instruction); + void read_access_chain(std::string *expr, const std::string &lhs, const SPIRAccessChain &chain); + void read_access_chain_struct(const std::string &lhs, const SPIRAccessChain &chain); + void read_access_chain_array(const std::string &lhs, const SPIRAccessChain &chain); + void write_access_chain(const SPIRAccessChain &chain, uint32_t value, const SmallVector &composite_chain); + void write_access_chain_struct(const SPIRAccessChain &chain, uint32_t value, + const SmallVector &composite_chain); + void write_access_chain_array(const SPIRAccessChain &chain, uint32_t value, + const SmallVector &composite_chain); + std::string write_access_chain_value(uint32_t value, const SmallVector &composite_chain, bool enclose); + void emit_store(const Instruction &instruction); + void emit_atomic(const uint32_t *ops, uint32_t length, spv::Op op); + void emit_subgroup_op(const Instruction &i) override; + void emit_block_hints(const SPIRBlock &block) override; + + void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, const std::string &qualifier, + uint32_t base_offset = 0) override; + + const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override; + void replace_illegal_names() override; + + Options hlsl_options; + + // TODO: Refactor this to be more similar to MSL, maybe have some common system in place? + bool requires_op_fmod = false; + bool requires_fp16_packing = false; + bool requires_uint2_packing = false; + bool requires_explicit_fp16_packing = false; + bool requires_unorm8_packing = false; + bool requires_snorm8_packing = false; + bool requires_unorm16_packing = false; + bool requires_snorm16_packing = false; + bool requires_bitfield_insert = false; + bool requires_bitfield_extract = false; + bool requires_inverse_2x2 = false; + bool requires_inverse_3x3 = false; + bool requires_inverse_4x4 = false; + bool requires_scalar_reflect = false; + bool requires_scalar_refract = false; + bool requires_scalar_faceforward = false; + uint64_t required_textureSizeVariants = 0; + void require_texture_query_variant(const SPIRType &type); + + enum TextureQueryVariantDim + { + Query1D = 0, + Query1DArray, + Query2D, + Query2DArray, + Query3D, + QueryBuffer, + QueryCube, + QueryCubeArray, + Query2DMS, + Query2DMSArray, + QueryDimCount + }; + + enum TextureQueryVariantType + { + QueryTypeFloat = 0, + QueryTypeInt = 16, + QueryTypeUInt = 32, + QueryTypeCount = 3 + }; + + enum BitcastType + { + TypeNormal, + TypePackUint2x32, + TypeUnpackUint64 + }; + + BitcastType get_bitcast_type(uint32_t result_type, uint32_t op0); + + void emit_builtin_variables(); + bool require_output = false; + bool require_input = false; + SmallVector remap_vertex_attributes; + + uint32_t type_to_consumed_locations(const SPIRType &type) const; + + void emit_io_block(const SPIRVariable &var); + std::string to_semantic(uint32_t location, spv::ExecutionModel em, spv::StorageClass sc); + + uint32_t num_workgroups_builtin = 0; + HLSLBindingFlags resource_binding_flags = 0; + + // Custom root constant layout, which should be emitted + // when translating push constant ranges. + std::vector root_constants_layout; + + void validate_shader_model(); + + std::string get_unique_identifier(); + uint32_t unique_identifier_count = 0; + + std::unordered_map, InternalHasher> resource_bindings; + void remap_hlsl_resource_binding(HLSLBindingFlagBits type, uint32_t &desc_set, uint32_t &binding); +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_msl.hpp b/ios/include/spirv_cross/spirv_msl.hpp new file mode 100644 index 00000000..e56d27b9 --- /dev/null +++ b/ios/include/spirv_cross/spirv_msl.hpp @@ -0,0 +1,962 @@ +/* + * Copyright 2016-2020 The Brenwill Workshop Ltd. + * + * 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 SPIRV_CROSS_MSL_HPP +#define SPIRV_CROSS_MSL_HPP + +#include "spirv_glsl.hpp" +#include +#include +#include +#include +#include + +namespace SPIRV_CROSS_NAMESPACE +{ + +// Indicates the format of the vertex attribute. Currently limited to specifying +// if the attribute is an 8-bit unsigned integer, 16-bit unsigned integer, or +// some other format. +enum MSLVertexFormat +{ + MSL_VERTEX_FORMAT_OTHER = 0, + MSL_VERTEX_FORMAT_UINT8 = 1, + MSL_VERTEX_FORMAT_UINT16 = 2, + MSL_VERTEX_FORMAT_INT_MAX = 0x7fffffff +}; + +// Defines MSL characteristics of a vertex attribute at a particular location. +// After compilation, it is possible to query whether or not this location was used. +struct MSLVertexAttr +{ + uint32_t location = 0; + uint32_t msl_buffer = 0; + uint32_t msl_offset = 0; + uint32_t msl_stride = 0; + bool per_instance = false; + MSLVertexFormat format = MSL_VERTEX_FORMAT_OTHER; + spv::BuiltIn builtin = spv::BuiltInMax; +}; + +// Matches the binding index of a MSL resource for a binding within a descriptor set. +// Taken together, the stage, desc_set and binding combine to form a reference to a resource +// descriptor used in a particular shading stage. +// If using MSL 2.0 argument buffers, the descriptor set is not marked as a discrete descriptor set, +// and (for iOS only) the resource is not a storage image (sampled != 2), the binding reference we +// remap to will become an [[id(N)]] attribute within the "descriptor set" argument buffer structure. +// For resources which are bound in the "classic" MSL 1.0 way or discrete descriptors, the remap will become a +// [[buffer(N)]], [[texture(N)]] or [[sampler(N)]] depending on the resource types used. +struct MSLResourceBinding +{ + spv::ExecutionModel stage = spv::ExecutionModelMax; + uint32_t desc_set = 0; + uint32_t binding = 0; + uint32_t msl_buffer = 0; + uint32_t msl_texture = 0; + uint32_t msl_sampler = 0; +}; + +enum MSLSamplerCoord +{ + MSL_SAMPLER_COORD_NORMALIZED = 0, + MSL_SAMPLER_COORD_PIXEL = 1, + MSL_SAMPLER_INT_MAX = 0x7fffffff +}; + +enum MSLSamplerFilter +{ + MSL_SAMPLER_FILTER_NEAREST = 0, + MSL_SAMPLER_FILTER_LINEAR = 1, + MSL_SAMPLER_FILTER_INT_MAX = 0x7fffffff +}; + +enum MSLSamplerMipFilter +{ + MSL_SAMPLER_MIP_FILTER_NONE = 0, + MSL_SAMPLER_MIP_FILTER_NEAREST = 1, + MSL_SAMPLER_MIP_FILTER_LINEAR = 2, + MSL_SAMPLER_MIP_FILTER_INT_MAX = 0x7fffffff +}; + +enum MSLSamplerAddress +{ + MSL_SAMPLER_ADDRESS_CLAMP_TO_ZERO = 0, + MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE = 1, + MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER = 2, + MSL_SAMPLER_ADDRESS_REPEAT = 3, + MSL_SAMPLER_ADDRESS_MIRRORED_REPEAT = 4, + MSL_SAMPLER_ADDRESS_INT_MAX = 0x7fffffff +}; + +enum MSLSamplerCompareFunc +{ + MSL_SAMPLER_COMPARE_FUNC_NEVER = 0, + MSL_SAMPLER_COMPARE_FUNC_LESS = 1, + MSL_SAMPLER_COMPARE_FUNC_LESS_EQUAL = 2, + MSL_SAMPLER_COMPARE_FUNC_GREATER = 3, + MSL_SAMPLER_COMPARE_FUNC_GREATER_EQUAL = 4, + MSL_SAMPLER_COMPARE_FUNC_EQUAL = 5, + MSL_SAMPLER_COMPARE_FUNC_NOT_EQUAL = 6, + MSL_SAMPLER_COMPARE_FUNC_ALWAYS = 7, + MSL_SAMPLER_COMPARE_FUNC_INT_MAX = 0x7fffffff +}; + +enum MSLSamplerBorderColor +{ + MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK = 0, + MSL_SAMPLER_BORDER_COLOR_OPAQUE_BLACK = 1, + MSL_SAMPLER_BORDER_COLOR_OPAQUE_WHITE = 2, + MSL_SAMPLER_BORDER_COLOR_INT_MAX = 0x7fffffff +}; + +enum MSLFormatResolution +{ + MSL_FORMAT_RESOLUTION_444 = 0, + MSL_FORMAT_RESOLUTION_422, + MSL_FORMAT_RESOLUTION_420, + MSL_FORMAT_RESOLUTION_INT_MAX = 0x7fffffff +}; + +enum MSLChromaLocation +{ + MSL_CHROMA_LOCATION_COSITED_EVEN = 0, + MSL_CHROMA_LOCATION_MIDPOINT, + MSL_CHROMA_LOCATION_INT_MAX = 0x7fffffff +}; + +enum MSLComponentSwizzle +{ + MSL_COMPONENT_SWIZZLE_IDENTITY = 0, + MSL_COMPONENT_SWIZZLE_ZERO, + MSL_COMPONENT_SWIZZLE_ONE, + MSL_COMPONENT_SWIZZLE_R, + MSL_COMPONENT_SWIZZLE_G, + MSL_COMPONENT_SWIZZLE_B, + MSL_COMPONENT_SWIZZLE_A, + MSL_COMPONENT_SWIZZLE_INT_MAX = 0x7fffffff +}; + +enum MSLSamplerYCbCrModelConversion +{ + MSL_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0, + MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY, + MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_709, + MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_601, + MSL_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_BT_2020, + MSL_SAMPLER_YCBCR_MODEL_CONVERSION_INT_MAX = 0x7fffffff +}; + +enum MSLSamplerYCbCrRange +{ + MSL_SAMPLER_YCBCR_RANGE_ITU_FULL = 0, + MSL_SAMPLER_YCBCR_RANGE_ITU_NARROW, + MSL_SAMPLER_YCBCR_RANGE_INT_MAX = 0x7fffffff +}; + +struct MSLConstexprSampler +{ + MSLSamplerCoord coord = MSL_SAMPLER_COORD_NORMALIZED; + MSLSamplerFilter min_filter = MSL_SAMPLER_FILTER_NEAREST; + MSLSamplerFilter mag_filter = MSL_SAMPLER_FILTER_NEAREST; + MSLSamplerMipFilter mip_filter = MSL_SAMPLER_MIP_FILTER_NONE; + MSLSamplerAddress s_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE; + MSLSamplerAddress t_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE; + MSLSamplerAddress r_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE; + MSLSamplerCompareFunc compare_func = MSL_SAMPLER_COMPARE_FUNC_NEVER; + MSLSamplerBorderColor border_color = MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK; + float lod_clamp_min = 0.0f; + float lod_clamp_max = 1000.0f; + int max_anisotropy = 1; + + // Sampler Y'CbCr conversion parameters + uint32_t planes = 0; + MSLFormatResolution resolution = MSL_FORMAT_RESOLUTION_444; + MSLSamplerFilter chroma_filter = MSL_SAMPLER_FILTER_NEAREST; + MSLChromaLocation x_chroma_offset = MSL_CHROMA_LOCATION_COSITED_EVEN; + MSLChromaLocation y_chroma_offset = MSL_CHROMA_LOCATION_COSITED_EVEN; + MSLComponentSwizzle swizzle[4]; // IDENTITY, IDENTITY, IDENTITY, IDENTITY + MSLSamplerYCbCrModelConversion ycbcr_model = MSL_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY; + MSLSamplerYCbCrRange ycbcr_range = MSL_SAMPLER_YCBCR_RANGE_ITU_FULL; + uint32_t bpc = 8; + + bool compare_enable = false; + bool lod_clamp_enable = false; + bool anisotropy_enable = false; + bool ycbcr_conversion_enable = false; + + MSLConstexprSampler() + { + for (uint32_t i = 0; i < 4; i++) + swizzle[i] = MSL_COMPONENT_SWIZZLE_IDENTITY; + } + bool swizzle_is_identity() const + { + return (swizzle[0] == MSL_COMPONENT_SWIZZLE_IDENTITY && swizzle[1] == MSL_COMPONENT_SWIZZLE_IDENTITY && + swizzle[2] == MSL_COMPONENT_SWIZZLE_IDENTITY && swizzle[3] == MSL_COMPONENT_SWIZZLE_IDENTITY); + } + bool swizzle_has_one_or_zero() const + { + return (swizzle[0] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[0] == MSL_COMPONENT_SWIZZLE_ONE || + swizzle[1] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[1] == MSL_COMPONENT_SWIZZLE_ONE || + swizzle[2] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[2] == MSL_COMPONENT_SWIZZLE_ONE || + swizzle[3] == MSL_COMPONENT_SWIZZLE_ZERO || swizzle[3] == MSL_COMPONENT_SWIZZLE_ONE); + } +}; + +// Special constant used in a MSLResourceBinding desc_set +// element to indicate the bindings for the push constants. +// Kinda deprecated. Just use ResourceBindingPushConstant{DescriptorSet,Binding} directly. +static const uint32_t kPushConstDescSet = ResourceBindingPushConstantDescriptorSet; + +// Special constant used in a MSLResourceBinding binding +// element to indicate the bindings for the push constants. +// Kinda deprecated. Just use ResourceBindingPushConstant{DescriptorSet,Binding} directly. +static const uint32_t kPushConstBinding = ResourceBindingPushConstantBinding; + +// Special constant used in a MSLResourceBinding binding +// element to indicate the buffer binding for swizzle buffers. +static const uint32_t kSwizzleBufferBinding = ~(1u); + +// Special constant used in a MSLResourceBinding binding +// element to indicate the buffer binding for buffer size buffers to support OpArrayLength. +static const uint32_t kBufferSizeBufferBinding = ~(2u); + +// Special constant used in a MSLResourceBinding binding +// element to indicate the buffer binding used for the argument buffer itself. +// This buffer binding should be kept as small as possible as all automatic bindings for buffers +// will start at max(kArgumentBufferBinding) + 1. +static const uint32_t kArgumentBufferBinding = ~(3u); + +static const uint32_t kMaxArgumentBuffers = 8; + +// Decompiles SPIR-V to Metal Shading Language +class CompilerMSL : public CompilerGLSL +{ +public: + // Options for compiling to Metal Shading Language + struct Options + { + typedef enum + { + iOS = 0, + macOS = 1 + } Platform; + + Platform platform = macOS; + uint32_t msl_version = make_msl_version(1, 2); + uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers + uint32_t swizzle_buffer_index = 30; + uint32_t indirect_params_buffer_index = 29; + uint32_t shader_output_buffer_index = 28; + uint32_t shader_patch_output_buffer_index = 27; + uint32_t shader_tess_factor_buffer_index = 26; + uint32_t buffer_size_buffer_index = 25; + uint32_t view_mask_buffer_index = 24; + uint32_t dynamic_offsets_buffer_index = 23; + uint32_t shader_input_wg_index = 0; + uint32_t device_index = 0; + uint32_t enable_frag_output_mask = 0xffffffff; + bool enable_point_size_builtin = true; + bool enable_frag_depth_builtin = true; + bool enable_frag_stencil_ref_builtin = true; + bool disable_rasterization = false; + bool capture_output_to_buffer = false; + bool swizzle_texture_samples = false; + bool tess_domain_origin_lower_left = false; + bool multiview = false; + bool view_index_from_device_index = false; + bool dispatch_base = false; + bool texture_1D_as_2D = false; + + // Enable use of MSL 2.0 indirect argument buffers. + // MSL 2.0 must also be enabled. + bool argument_buffers = false; + + // Ensures vertex and instance indices start at zero. This reflects the behavior of HLSL with SV_VertexID and SV_InstanceID. + bool enable_base_index_zero = false; + + // Fragment output in MSL must have at least as many components as the render pass. + // Add support to explicit pad out components. + bool pad_fragment_output_components = false; + + // Specifies whether the iOS target version supports the [[base_vertex]] and [[base_instance]] attributes. + bool ios_support_base_vertex_instance = false; + + // Use Metal's native frame-buffer fetch API for subpass inputs. + bool ios_use_framebuffer_fetch_subpasses = false; + + // Enables use of "fma" intrinsic for invariant float math + bool invariant_float_math = false; + + // Emulate texturecube_array with texture2d_array for iOS where this type is not available + bool emulate_cube_array = false; + + // Allow user to enable decoration binding + bool enable_decoration_binding = false; + + // Requires MSL 2.1, use the native support for texel buffers. + bool texture_buffer_native = false; + + // Forces all resources which are part of an argument buffer to be considered active. + // This ensures ABI compatibility between shaders where some resources might be unused, + // and would otherwise declare a different IAB. + bool force_active_argument_buffer_resources = false; + + // Forces the use of plain arrays, which works around certain driver bugs on certain versions + // of Intel Macbooks. See https://github.com/KhronosGroup/SPIRV-Cross/issues/1210. + // May reduce performance in scenarios where arrays are copied around as value-types. + bool force_native_arrays = false; + + // If a shader writes clip distance, also emit user varyings which + // can be read in subsequent stages. + bool enable_clip_distance_user_varying = true; + + bool is_ios() const + { + return platform == iOS; + } + + bool is_macos() const + { + return platform == macOS; + } + + void set_msl_version(uint32_t major, uint32_t minor = 0, uint32_t patch = 0) + { + msl_version = make_msl_version(major, minor, patch); + } + + bool supports_msl_version(uint32_t major, uint32_t minor = 0, uint32_t patch = 0) const + { + return msl_version >= make_msl_version(major, minor, patch); + } + + static uint32_t make_msl_version(uint32_t major, uint32_t minor = 0, uint32_t patch = 0) + { + return (major * 10000) + (minor * 100) + patch; + } + }; + + const Options &get_msl_options() const + { + return msl_options; + } + + void set_msl_options(const Options &opts) + { + msl_options = opts; + } + + // Provide feedback to calling API to allow runtime to disable pipeline + // rasterization if vertex shader requires rasterization to be disabled. + bool get_is_rasterization_disabled() const + { + return is_rasterization_disabled && (get_entry_point().model == spv::ExecutionModelVertex || + get_entry_point().model == spv::ExecutionModelTessellationControl || + get_entry_point().model == spv::ExecutionModelTessellationEvaluation); + } + + // Provide feedback to calling API to allow it to pass an auxiliary + // swizzle buffer if the shader needs it. + bool needs_swizzle_buffer() const + { + return used_swizzle_buffer; + } + + // Provide feedback to calling API to allow it to pass a buffer + // containing STORAGE_BUFFER buffer sizes to support OpArrayLength. + bool needs_buffer_size_buffer() const + { + return !buffers_requiring_array_length.empty(); + } + + // Provide feedback to calling API to allow it to pass a buffer + // containing the view mask for the current multiview subpass. + bool needs_view_mask_buffer() const + { + return msl_options.multiview && !msl_options.view_index_from_device_index; + } + + // Provide feedback to calling API to allow it to pass a buffer + // containing the dispatch base workgroup ID. + bool needs_dispatch_base_buffer() const + { + return msl_options.dispatch_base && !msl_options.supports_msl_version(1, 2); + } + + // Provide feedback to calling API to allow it to pass an output + // buffer if the shader needs it. + bool needs_output_buffer() const + { + return capture_output_to_buffer && stage_out_var_id != ID(0); + } + + // Provide feedback to calling API to allow it to pass a patch output + // buffer if the shader needs it. + bool needs_patch_output_buffer() const + { + return capture_output_to_buffer && patch_stage_out_var_id != ID(0); + } + + // Provide feedback to calling API to allow it to pass an input threadgroup + // buffer if the shader needs it. + bool needs_input_threadgroup_mem() const + { + return capture_output_to_buffer && stage_in_var_id != ID(0); + } + + explicit CompilerMSL(std::vector spirv); + CompilerMSL(const uint32_t *ir, size_t word_count); + explicit CompilerMSL(const ParsedIR &ir); + explicit CompilerMSL(ParsedIR &&ir); + + // attr is a vertex attribute binding used to match + // vertex content locations to MSL attributes. If vertex attributes are provided, + // is_msl_vertex_attribute_used() will return true after calling ::compile() if + // the location was used by the MSL code. + void add_msl_vertex_attribute(const MSLVertexAttr &attr); + + // resource is a resource binding to indicate the MSL buffer, + // texture or sampler index to use for a particular SPIR-V description set + // and binding. If resource bindings are provided, + // is_msl_resource_binding_used() will return true after calling ::compile() if + // the set/binding combination was used by the MSL code. + void add_msl_resource_binding(const MSLResourceBinding &resource); + + // desc_set and binding are the SPIR-V descriptor set and binding of a buffer resource + // in this shader. index is the index within the dynamic offset buffer to use. This + // function marks that resource as using a dynamic offset (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + // or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC). This function only has any effect if argument buffers + // are enabled. If so, the buffer will have its address adjusted at the beginning of the shader with + // an offset taken from the dynamic offset buffer. + void add_dynamic_buffer(uint32_t desc_set, uint32_t binding, uint32_t index); + + // desc_set and binding are the SPIR-V descriptor set and binding of a buffer resource + // in this shader. This function marks that resource as an inline uniform block + // (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT). This function only has any effect if argument buffers + // are enabled. If so, the buffer block will be directly embedded into the argument + // buffer, instead of being referenced indirectly via pointer. + void add_inline_uniform_block(uint32_t desc_set, uint32_t binding); + + // When using MSL argument buffers, we can force "classic" MSL 1.0 binding schemes for certain descriptor sets. + // This corresponds to VK_KHR_push_descriptor in Vulkan. + void add_discrete_descriptor_set(uint32_t desc_set); + + // If an argument buffer is large enough, it may need to be in the device storage space rather than + // constant. Opt-in to this behavior here on a per set basis. + void set_argument_buffer_device_address_space(uint32_t desc_set, bool device_storage); + + // Query after compilation is done. This allows you to check if a location or set/binding combination was used by the shader. + bool is_msl_vertex_attribute_used(uint32_t location); + + // NOTE: Only resources which are remapped using add_msl_resource_binding will be reported here. + // Constexpr samplers are always assumed to be emitted. + // No specific MSLResourceBinding remapping is required for constexpr samplers as long as they are remapped + // by remap_constexpr_sampler(_by_binding). + bool is_msl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding) const; + + // This must only be called after a successful call to CompilerMSL::compile(). + // For a variable resource ID obtained through reflection API, report the automatically assigned resource index. + // If the descriptor set was part of an argument buffer, report the [[id(N)]], + // or [[buffer/texture/sampler]] binding for other resources. + // If the resource was a combined image sampler, report the image binding here, + // use the _secondary version of this call to query the sampler half of the resource. + // If no binding exists, uint32_t(-1) is returned. + uint32_t get_automatic_msl_resource_binding(uint32_t id) const; + + // Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers, in which case the + // sampler's binding is returned instead. For any other resource type, -1 is returned. + uint32_t get_automatic_msl_resource_binding_secondary(uint32_t id) const; + + // Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers for multiplanar images, + // in which case the second plane's binding is returned instead. For any other resource type, -1 is returned. + uint32_t get_automatic_msl_resource_binding_tertiary(uint32_t id) const; + + // Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers for triplanar images, + // in which case the third plane's binding is returned instead. For any other resource type, -1 is returned. + uint32_t get_automatic_msl_resource_binding_quaternary(uint32_t id) const; + + // Compiles the SPIR-V code into Metal Shading Language. + std::string compile() override; + + // Remap a sampler with ID to a constexpr sampler. + // Older iOS targets must use constexpr samplers in certain cases (PCF), + // so a static sampler must be used. + // The sampler will not consume a binding, but be declared in the entry point as a constexpr sampler. + // This can be used on both combined image/samplers (sampler2D) or standalone samplers. + // The remapped sampler must not be an array of samplers. + // Prefer remap_constexpr_sampler_by_binding unless you're also doing reflection anyways. + void remap_constexpr_sampler(VariableID id, const MSLConstexprSampler &sampler); + + // Same as remap_constexpr_sampler, except you provide set/binding, rather than variable ID. + // Remaps based on ID take priority over set/binding remaps. + void remap_constexpr_sampler_by_binding(uint32_t desc_set, uint32_t binding, const MSLConstexprSampler &sampler); + + // If using CompilerMSL::Options::pad_fragment_output_components, override the number of components we expect + // to use for a particular location. The default is 4 if number of components is not overridden. + void set_fragment_output_components(uint32_t location, uint32_t components); + +protected: + // An enum of SPIR-V functions that are implemented in additional + // source code that is added to the shader if necessary. + enum SPVFuncImpl + { + SPVFuncImplNone, + SPVFuncImplMod, + SPVFuncImplRadians, + SPVFuncImplDegrees, + SPVFuncImplFindILsb, + SPVFuncImplFindSMsb, + SPVFuncImplFindUMsb, + SPVFuncImplSSign, + SPVFuncImplArrayCopyMultidimBase, + // Unfortunately, we cannot use recursive templates in the MSL compiler properly, + // so stamp out variants up to some arbitrary maximum. + SPVFuncImplArrayCopy = SPVFuncImplArrayCopyMultidimBase + 1, + SPVFuncImplArrayOfArrayCopy2Dim = SPVFuncImplArrayCopyMultidimBase + 2, + SPVFuncImplArrayOfArrayCopy3Dim = SPVFuncImplArrayCopyMultidimBase + 3, + SPVFuncImplArrayOfArrayCopy4Dim = SPVFuncImplArrayCopyMultidimBase + 4, + SPVFuncImplArrayOfArrayCopy5Dim = SPVFuncImplArrayCopyMultidimBase + 5, + SPVFuncImplArrayOfArrayCopy6Dim = SPVFuncImplArrayCopyMultidimBase + 6, + SPVFuncImplTexelBufferCoords, + SPVFuncImplImage2DAtomicCoords, // Emulate texture2D atomic operations + SPVFuncImplFMul, + SPVFuncImplFAdd, + SPVFuncImplCubemapTo2DArrayFace, + SPVFuncImplUnsafeArray, // Allow Metal to use the array template to make arrays a value type + SPVFuncImplInverse4x4, + SPVFuncImplInverse3x3, + SPVFuncImplInverse2x2, + // It is very important that this come before *Swizzle and ChromaReconstruct*, to ensure it's + // emitted before them. + SPVFuncImplForwardArgs, + // Likewise, this must come before *Swizzle. + SPVFuncImplGetSwizzle, + SPVFuncImplTextureSwizzle, + SPVFuncImplGatherSwizzle, + SPVFuncImplGatherCompareSwizzle, + SPVFuncImplSubgroupBallot, + SPVFuncImplSubgroupBallotBitExtract, + SPVFuncImplSubgroupBallotFindLSB, + SPVFuncImplSubgroupBallotFindMSB, + SPVFuncImplSubgroupBallotBitCount, + SPVFuncImplSubgroupAllEqual, + SPVFuncImplReflectScalar, + SPVFuncImplRefractScalar, + SPVFuncImplFaceForwardScalar, + SPVFuncImplChromaReconstructNearest2Plane, + SPVFuncImplChromaReconstructNearest3Plane, + SPVFuncImplChromaReconstructLinear422CositedEven2Plane, + SPVFuncImplChromaReconstructLinear422CositedEven3Plane, + SPVFuncImplChromaReconstructLinear422Midpoint2Plane, + SPVFuncImplChromaReconstructLinear422Midpoint3Plane, + SPVFuncImplChromaReconstructLinear420XCositedEvenYCositedEven2Plane, + SPVFuncImplChromaReconstructLinear420XCositedEvenYCositedEven3Plane, + SPVFuncImplChromaReconstructLinear420XMidpointYCositedEven2Plane, + SPVFuncImplChromaReconstructLinear420XMidpointYCositedEven3Plane, + SPVFuncImplChromaReconstructLinear420XCositedEvenYMidpoint2Plane, + SPVFuncImplChromaReconstructLinear420XCositedEvenYMidpoint3Plane, + SPVFuncImplChromaReconstructLinear420XMidpointYMidpoint2Plane, + SPVFuncImplChromaReconstructLinear420XMidpointYMidpoint3Plane, + SPVFuncImplExpandITUFullRange, + SPVFuncImplExpandITUNarrowRange, + SPVFuncImplConvertYCbCrBT709, + SPVFuncImplConvertYCbCrBT601, + SPVFuncImplConvertYCbCrBT2020, + SPVFuncImplDynamicImageSampler, + + SPVFuncImplArrayCopyMultidimMax = 6 + }; + + // If the underlying resource has been used for comparison then duplicate loads of that resource must be too + // Use Metal's native frame-buffer fetch API for subpass inputs. + void emit_texture_op(const Instruction &i) override; + void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op); + void emit_instruction(const Instruction &instr) override; + void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args, + uint32_t count) override; + void emit_spv_amd_shader_trinary_minmax_op(uint32_t result_type, uint32_t result_id, uint32_t op, + const uint32_t *args, uint32_t count) override; + void emit_header() override; + void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override; + void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override; + void emit_subgroup_op(const Instruction &i) override; + std::string to_texture_op(const Instruction &i, bool *forward, + SmallVector &inherited_expressions) override; + void emit_fixup() override; + std::string to_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, + const std::string &qualifier = ""); + void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, + const std::string &qualifier = "", uint32_t base_offset = 0) override; + void emit_struct_padding_target(const SPIRType &type) override; + std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override; + + // Allow Metal to use the array template to make arrays a value type + std::string type_to_array_glsl(const SPIRType &type) override; + + // Threadgroup arrays can't have a wrapper type + std::string variable_decl(const SPIRVariable &variable) override; + + // GCC workaround of lambdas calling protected functions (for older GCC versions) + std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0) override; + + std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override; + std::string sampler_type(const SPIRType &type); + std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override; + std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override; + std::string to_name(uint32_t id, bool allow_alias = true) const override; + std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, + bool has_array_offsets, bool has_offset, bool has_grad, bool has_dref, uint32_t lod, + uint32_t minlod) override; + std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, + uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x, + uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, + uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) override; + std::string to_initializer_expression(const SPIRVariable &var) override; + std::string to_zero_initialized_expression(uint32_t type_id) override; + + std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t physical_type_id, + bool is_packed, bool row_major) override; + + // Returns true for BuiltInSampleMask because gl_SampleMask[] is an array in SPIR-V, but [[sample_mask]] is a scalar in Metal. + bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override; + + std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override; + bool emit_complex_bitcast(uint32_t result_id, uint32_t id, uint32_t op0) override; + bool skip_argument(uint32_t id) const override; + std::string to_member_reference(uint32_t base, const SPIRType &type, uint32_t index, bool ptr_chain) override; + std::string to_qualifiers_glsl(uint32_t id) override; + void replace_illegal_names() override; + void declare_undefined_values() override; + void declare_constant_arrays(); + + // Constant arrays of non-primitive types (i.e. matrices) won't link properly into Metal libraries + void declare_complex_constant_arrays(); + + bool is_patch_block(const SPIRType &type); + bool is_non_native_row_major_matrix(uint32_t id) override; + bool member_is_non_native_row_major_matrix(const SPIRType &type, uint32_t index) override; + std::string convert_row_major_matrix(std::string exp_str, const SPIRType &exp_type, uint32_t physical_type_id, + bool is_packed) override; + + void preprocess_op_codes(); + void localize_global_variables(); + void extract_global_variables_from_functions(); + void mark_packable_structs(); + void mark_as_packable(SPIRType &type); + + std::unordered_map> function_global_vars; + void extract_global_variables_from_function(uint32_t func_id, std::set &added_arg_ids, + std::unordered_set &global_var_ids, + std::unordered_set &processed_func_ids); + uint32_t add_interface_block(spv::StorageClass storage, bool patch = false); + uint32_t add_interface_block_pointer(uint32_t ib_var_id, spv::StorageClass storage); + + struct InterfaceBlockMeta + { + struct LocationMeta + { + uint32_t num_components = 0; + uint32_t ib_index = ~0u; + }; + std::unordered_map location_meta; + bool strip_array = false; + }; + + void add_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, SPIRType &ib_type, + SPIRVariable &var, InterfaceBlockMeta &meta); + void add_composite_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, + SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta); + void add_plain_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, + SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta); + void add_plain_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, + SPIRType &ib_type, SPIRVariable &var, uint32_t index, + InterfaceBlockMeta &meta); + void add_composite_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref, + SPIRType &ib_type, SPIRVariable &var, uint32_t index, + InterfaceBlockMeta &meta); + uint32_t get_accumulated_member_location(const SPIRVariable &var, uint32_t mbr_idx, bool strip_array); + void add_tess_level_input_to_interface_block(const std::string &ib_var_ref, SPIRType &ib_type, SPIRVariable &var); + + void fix_up_interface_member_indices(spv::StorageClass storage, uint32_t ib_type_id); + + void mark_location_as_used_by_shader(uint32_t location, spv::StorageClass storage); + uint32_t ensure_correct_builtin_type(uint32_t type_id, spv::BuiltIn builtin); + uint32_t ensure_correct_attribute_type(uint32_t type_id, uint32_t location, uint32_t num_components = 0); + + void emit_custom_templates(); + void emit_custom_functions(); + void emit_resources(); + void emit_specialization_constants_and_structs(); + void emit_interface_block(uint32_t ib_var_id); + bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs); + + void fix_up_shader_inputs_outputs(); + + std::string func_type_decl(SPIRType &type); + std::string entry_point_args_classic(bool append_comma); + std::string entry_point_args_argument_buffer(bool append_comma); + std::string entry_point_arg_stage_in(); + void entry_point_args_builtin(std::string &args); + void entry_point_args_discrete_descriptors(std::string &args); + std::string to_qualified_member_name(const SPIRType &type, uint32_t index); + std::string ensure_valid_name(std::string name, std::string pfx); + std::string to_sampler_expression(uint32_t id); + std::string to_swizzle_expression(uint32_t id); + std::string to_buffer_size_expression(uint32_t id); + std::string builtin_qualifier(spv::BuiltIn builtin); + std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0); + std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma); + std::string member_attribute_qualifier(const SPIRType &type, uint32_t index); + std::string argument_decl(const SPIRFunction::Parameter &arg); + std::string round_fp_tex_coords(std::string tex_coords, bool coord_is_fp); + uint32_t get_metal_resource_index(SPIRVariable &var, SPIRType::BaseType basetype, uint32_t plane = 0); + uint32_t get_ordered_member_location(uint32_t type_id, uint32_t index, uint32_t *comp = nullptr); + + // MSL packing rules. These compute the effective packing rules as observed by the MSL compiler in the MSL output. + // These values can change depending on various extended decorations which control packing rules. + // We need to make these rules match up with SPIR-V declared rules. + uint32_t get_declared_type_size_msl(const SPIRType &type, bool packed, bool row_major) const; + uint32_t get_declared_type_array_stride_msl(const SPIRType &type, bool packed, bool row_major) const; + uint32_t get_declared_type_matrix_stride_msl(const SPIRType &type, bool packed, bool row_major) const; + uint32_t get_declared_type_alignment_msl(const SPIRType &type, bool packed, bool row_major) const; + + uint32_t get_declared_struct_member_size_msl(const SPIRType &struct_type, uint32_t index) const; + uint32_t get_declared_struct_member_array_stride_msl(const SPIRType &struct_type, uint32_t index) const; + uint32_t get_declared_struct_member_matrix_stride_msl(const SPIRType &struct_type, uint32_t index) const; + uint32_t get_declared_struct_member_alignment_msl(const SPIRType &struct_type, uint32_t index) const; + + const SPIRType &get_physical_member_type(const SPIRType &struct_type, uint32_t index) const; + + uint32_t get_declared_struct_size_msl(const SPIRType &struct_type, bool ignore_alignment = false, + bool ignore_padding = false) const; + + std::string to_component_argument(uint32_t id); + void align_struct(SPIRType &ib_type, std::unordered_set &aligned_structs); + void mark_scalar_layout_structs(const SPIRType &ib_type); + void mark_struct_members_packed(const SPIRType &type); + void ensure_member_packing_rules_msl(SPIRType &ib_type, uint32_t index); + bool validate_member_packing_rules_msl(const SPIRType &type, uint32_t index) const; + std::string get_argument_address_space(const SPIRVariable &argument); + std::string get_type_address_space(const SPIRType &type, uint32_t id, bool argument = false); + const char *to_restrict(uint32_t id, bool space = true); + SPIRType &get_stage_in_struct_type(); + SPIRType &get_stage_out_struct_type(); + SPIRType &get_patch_stage_in_struct_type(); + SPIRType &get_patch_stage_out_struct_type(); + std::string get_tess_factor_struct_name(); + void emit_atomic_func_op(uint32_t result_type, uint32_t result_id, const char *op, uint32_t mem_order_1, + uint32_t mem_order_2, bool has_mem_order_2, uint32_t op0, uint32_t op1 = 0, + bool op1_is_pointer = false, bool op1_is_literal = false, uint32_t op2 = 0); + const char *get_memory_order(uint32_t spv_mem_sem); + void add_pragma_line(const std::string &line); + void add_typedef_line(const std::string &line); + void emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem); + void emit_array_copy(const std::string &lhs, uint32_t rhs_id, spv::StorageClass lhs_storage, + spv::StorageClass rhs_storage) override; + void build_implicit_builtins(); + uint32_t build_constant_uint_array_pointer(); + void emit_entry_point_declarations() override; + uint32_t builtin_frag_coord_id = 0; + uint32_t builtin_sample_id_id = 0; + uint32_t builtin_vertex_idx_id = 0; + uint32_t builtin_base_vertex_id = 0; + uint32_t builtin_instance_idx_id = 0; + uint32_t builtin_base_instance_id = 0; + uint32_t builtin_view_idx_id = 0; + uint32_t builtin_layer_id = 0; + uint32_t builtin_invocation_id_id = 0; + uint32_t builtin_primitive_id_id = 0; + uint32_t builtin_subgroup_invocation_id_id = 0; + uint32_t builtin_subgroup_size_id = 0; + uint32_t builtin_dispatch_base_id = 0; + uint32_t swizzle_buffer_id = 0; + uint32_t buffer_size_buffer_id = 0; + uint32_t view_mask_buffer_id = 0; + uint32_t dynamic_offsets_buffer_id = 0; + + void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override; + void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override; + void emit_store_statement(uint32_t lhs_expression, uint32_t rhs_expression) override; + + void analyze_sampled_image_usage(); + + bool emit_tessellation_access_chain(const uint32_t *ops, uint32_t length); + bool emit_tessellation_io_load(uint32_t result_type, uint32_t id, uint32_t ptr); + bool is_out_of_bounds_tessellation_level(uint32_t id_lhs); + + void ensure_builtin(spv::StorageClass storage, spv::BuiltIn builtin); + + void mark_implicit_builtin(spv::StorageClass storage, spv::BuiltIn builtin, uint32_t id); + + std::string convert_to_f32(const std::string &expr, uint32_t components); + + Options msl_options; + std::set spv_function_implementations; + std::unordered_map vtx_attrs_by_location; + std::unordered_map vtx_attrs_by_builtin; + std::unordered_set vtx_attrs_in_use; + std::unordered_map fragment_output_components; + std::set pragma_lines; + std::set typedef_lines; + SmallVector vars_needing_early_declaration; + + std::unordered_map, InternalHasher> resource_bindings; + + uint32_t next_metal_resource_index_buffer = 0; + uint32_t next_metal_resource_index_texture = 0; + uint32_t next_metal_resource_index_sampler = 0; + // Intentionally uninitialized, works around MSVC 2013 bug. + uint32_t next_metal_resource_ids[kMaxArgumentBuffers]; + + VariableID stage_in_var_id = 0; + VariableID stage_out_var_id = 0; + VariableID patch_stage_in_var_id = 0; + VariableID patch_stage_out_var_id = 0; + VariableID stage_in_ptr_var_id = 0; + VariableID stage_out_ptr_var_id = 0; + + // Handle HLSL-style 0-based vertex/instance index. + enum class TriState + { + Neutral, + No, + Yes + }; + TriState needs_base_vertex_arg = TriState::Neutral; + TriState needs_base_instance_arg = TriState::Neutral; + + bool has_sampled_images = false; + bool builtin_declaration = false; // Handle HLSL-style 0-based vertex/instance index. + + bool is_using_builtin_array = false; // Force the use of C style array declaration. + bool using_builtin_array() const; + + bool is_rasterization_disabled = false; + bool capture_output_to_buffer = false; + bool needs_swizzle_buffer_def = false; + bool used_swizzle_buffer = false; + bool added_builtin_tess_level = false; + bool needs_subgroup_invocation_id = false; + std::string qual_pos_var_name; + std::string stage_in_var_name = "in"; + std::string stage_out_var_name = "out"; + std::string patch_stage_in_var_name = "patchIn"; + std::string patch_stage_out_var_name = "patchOut"; + std::string sampler_name_suffix = "Smplr"; + std::string swizzle_name_suffix = "Swzl"; + std::string buffer_size_name_suffix = "BufferSize"; + std::string plane_name_suffix = "Plane"; + std::string input_wg_var_name = "gl_in"; + std::string output_buffer_var_name = "spvOut"; + std::string patch_output_buffer_var_name = "spvPatchOut"; + std::string tess_factor_buffer_var_name = "spvTessLevel"; + spv::Op previous_instruction_opcode = spv::OpNop; + + // Must be ordered since declaration is in a specific order. + std::map constexpr_samplers_by_id; + std::unordered_map constexpr_samplers_by_binding; + const MSLConstexprSampler *find_constexpr_sampler(uint32_t id) const; + + std::unordered_set buffers_requiring_array_length; + SmallVector buffer_arrays; + std::unordered_set atomic_image_vars; // Emulate texture2D atomic operations + + // Must be ordered since array is in a specific order. + std::map> buffers_requiring_dynamic_offset; + + SmallVector disabled_frag_outputs; + + std::unordered_set inline_uniform_blocks; + + uint32_t argument_buffer_ids[kMaxArgumentBuffers]; + uint32_t argument_buffer_discrete_mask = 0; + uint32_t argument_buffer_device_storage_mask = 0; + + void analyze_argument_buffers(); + bool descriptor_set_is_argument_buffer(uint32_t desc_set) const; + + uint32_t get_target_components_for_fragment_location(uint32_t location) const; + uint32_t build_extended_vector_type(uint32_t type_id, uint32_t components); + + bool suppress_missing_prototypes = false; + + void add_spv_func_and_recompile(SPVFuncImpl spv_func); + + void activate_argument_buffer_resources(); + + bool type_is_msl_framebuffer_fetch(const SPIRType &type) const; + + // OpcodeHandler that handles several MSL preprocessing operations. + struct OpCodePreprocessor : OpcodeHandler + { + OpCodePreprocessor(CompilerMSL &compiler_) + : compiler(compiler_) + { + } + + bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override; + CompilerMSL::SPVFuncImpl get_spv_func_impl(spv::Op opcode, const uint32_t *args); + void check_resource_write(uint32_t var_id); + + CompilerMSL &compiler; + std::unordered_map result_types; + std::unordered_map image_pointers; // Emulate texture2D atomic operations + bool suppress_missing_prototypes = false; + bool uses_atomics = false; + bool uses_resource_write = false; + bool needs_subgroup_invocation_id = false; + }; + + // OpcodeHandler that scans for uses of sampled images + struct SampledImageScanner : OpcodeHandler + { + SampledImageScanner(CompilerMSL &compiler_) + : compiler(compiler_) + { + } + + bool handle(spv::Op opcode, const uint32_t *args, uint32_t) override; + + CompilerMSL &compiler; + }; + + // Sorts the members of a SPIRType and associated Meta info based on a settable sorting + // aspect, which defines which aspect of the struct members will be used to sort them. + // Regardless of the sorting aspect, built-in members always appear at the end of the struct. + struct MemberSorter + { + enum SortAspect + { + Location, + LocationReverse, + Offset, + OffsetThenLocationReverse, + Alphabetical + }; + + void sort(); + bool operator()(uint32_t mbr_idx1, uint32_t mbr_idx2); + MemberSorter(SPIRType &t, Meta &m, SortAspect sa); + + SPIRType &type; + Meta &meta; + SortAspect sort_aspect; + }; +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_parser.hpp b/ios/include/spirv_cross/spirv_parser.hpp new file mode 100644 index 00000000..dafa3e86 --- /dev/null +++ b/ios/include/spirv_cross/spirv_parser.hpp @@ -0,0 +1,93 @@ +/* + * Copyright 2018-2020 Arm Limited + * + * 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 SPIRV_CROSS_PARSER_HPP +#define SPIRV_CROSS_PARSER_HPP + +#include "spirv_cross_parsed_ir.hpp" +#include + +namespace SPIRV_CROSS_NAMESPACE +{ +class Parser +{ +public: + Parser(const uint32_t *spirv_data, size_t word_count); + Parser(std::vector spirv); + + void parse(); + + ParsedIR &get_parsed_ir() + { + return ir; + } + +private: + ParsedIR ir; + SPIRFunction *current_function = nullptr; + SPIRBlock *current_block = nullptr; + + void parse(const Instruction &instr); + const uint32_t *stream(const Instruction &instr) const; + + template + T &set(uint32_t id, P &&... args) + { + ir.add_typed_id(static_cast(T::type), id); + auto &var = variant_set(ir.ids[id], std::forward

(args)...); + var.self = id; + return var; + } + + template + T &get(uint32_t id) + { + return variant_get(ir.ids[id]); + } + + template + T *maybe_get(uint32_t id) + { + if (ir.ids[id].get_type() == static_cast(T::type)) + return &get(id); + else + return nullptr; + } + + template + const T &get(uint32_t id) const + { + return variant_get(ir.ids[id]); + } + + template + const T *maybe_get(uint32_t id) const + { + if (ir.ids[id].get_type() == T::type) + return &get(id); + else + return nullptr; + } + + // This must be an ordered data structure so we always pick the same type aliases. + SmallVector global_struct_cache; + + bool types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const; + bool variable_storage_is_aliased(const SPIRVariable &v) const; +}; +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/include/spirv_cross/spirv_reflect.hpp b/ios/include/spirv_cross/spirv_reflect.hpp new file mode 100644 index 00000000..844d3f1e --- /dev/null +++ b/ios/include/spirv_cross/spirv_reflect.hpp @@ -0,0 +1,83 @@ +/* + * Copyright 2018-2020 Bradley Austin Davis + * + * 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 SPIRV_CROSS_REFLECT_HPP +#define SPIRV_CROSS_REFLECT_HPP + +#include "spirv_glsl.hpp" +#include + +namespace simple_json +{ +class Stream; +} + +namespace SPIRV_CROSS_NAMESPACE +{ +class CompilerReflection : public CompilerGLSL +{ + using Parent = CompilerGLSL; + +public: + explicit CompilerReflection(std::vector spirv_) + : Parent(std::move(spirv_)) + { + options.vulkan_semantics = true; + } + + CompilerReflection(const uint32_t *ir_, size_t word_count) + : Parent(ir_, word_count) + { + options.vulkan_semantics = true; + } + + explicit CompilerReflection(const ParsedIR &ir_) + : CompilerGLSL(ir_) + { + options.vulkan_semantics = true; + } + + explicit CompilerReflection(ParsedIR &&ir_) + : CompilerGLSL(std::move(ir_)) + { + options.vulkan_semantics = true; + } + + void set_format(const std::string &format); + std::string compile() override; + +private: + static std::string execution_model_to_str(spv::ExecutionModel model); + + void emit_entry_points(); + void emit_types(); + void emit_resources(); + void emit_specialization_constants(); + + void emit_type(const SPIRType &type, bool &emitted_open_tag); + void emit_type_member(const SPIRType &type, uint32_t index); + void emit_type_member_qualifiers(const SPIRType &type, uint32_t index); + void emit_type_array(const SPIRType &type); + void emit_resources(const char *tag, const SmallVector &resources); + + std::string to_member_name(const SPIRType &type, uint32_t index) const; + + std::shared_ptr json_stream; +}; + +} // namespace SPIRV_CROSS_NAMESPACE + +#endif diff --git a/ios/libs/libOGLCompiler.a b/ios/libs/libOGLCompiler.a new file mode 100644 index 0000000000000000000000000000000000000000..cf8ab5d069b3118d50ebc89795e2cecfac391dc8 GIT binary patch literal 2608 zcma)8O>7%Q6n;)ZsRI3hM4|{Jw){xBBLoVBgQoQdh_sodmr&atcs8=V!o9owGF<-m5MtAj#}mESm< zFPyZ>^9z+io?s)~!K@6?Ga9EfRy4LXehL)g&2v+i)UtA0mmK>{s}WS{ZRvW2%iS)A zU8S~PlgrDdFPoQvTdVg@9FLs6Q?pK##NrKCHQtkFTAo}j5SevJ*C-lCeNvZ69a0@k z)bdJ=`FKmBAMgM9;Bg{UCF%x%r9N~P8tiGbUqf$5|J!jaY)Ru?9s4NexIMy7m=J+n z4We*Mr$v4GzS(&S} zl&d0UR`ZPqJKr)tj`+||l*7tz^7!waou`KM{AT~qwe2f&>s#|be7(^xen~%@pPSa) zB-&Hcg5JY)C|(=hgLN}lPn?5w4ezIcdSC4zC)TJ!i#cl`ckQ2kx`x^hbA8Nr;<+#v zai61RrXTrT_C6SniarvFi|5%+qxJIN2)#sn=z94N>hp(v?CHMzMB%xbhW z0>b(Ga2`gBZHqa6cX##NU(E4Cj{kp78~hIQ0iyW-4gQ+JzcTc?zs3{uWpT1C zWu;h-KA0urbDcxLDH*_j-c>8IVERua-^h~ht4PGqn1sfhQhsgsDMrA4cY=LC`_4Gl zc1rn+t}6Pqx6S*+)PhvfU6y-C>~m2uFC$7Qb-6hff2A~)%|+>X(i>~~-ingl)#c)q zyNXw~MOVn4_m=c^Dw}1I@HWLY4om3!P5%P? CaqFi5 literal 0 HcmV?d00001 diff --git a/ios/libs/libOSDependent.a b/ios/libs/libOSDependent.a new file mode 100644 index 0000000000000000000000000000000000000000..9830bf28bca80bbeebd7d4b010d3ecf8186b308d GIT binary patch literal 3768 zcmb7HOKclO7#`c9NgtFR3WZYWLW`6N670lz90+w9rw_?VO6*o`r83>@PGT$T2ll#6 zaV3n3ARrF0!~t=kJs{PnpdL7IKq538dO#vUsOqtmdWfiyKvbeZHRbzvXJdQa)Z&+C zzWJZ?`giyD3$LkJE&lq3U4d7-{7RJqJ^lTC!QTF0Kv8=9=oDKW@cVm%K}8Ar(OGnA z1LvL5<0IkW{YrFfJT@F=po7$bZg?1bUgChnlM;&(FG{>B@wUYE@Fjmg8s{fQ`=*SX zp{Aw+-3Nquz(`N1MkK9G51+2r1`nkYk5Z3CIs9Xh=uy?ki{Zm=cj%*a`lz4R&(H&t z{aGOp<4{T$GYv6%VK8VIX>HZQHA&yNFoc>DYwn`Uj}Sw!N#!%Kcvh%-ST$AGR=WZ) z3g?rV5s^%1&km*YDN|%~uww4}ti4-%Z1>K6c6W96I`^5*< z7{g82-DAKjUUUi?=oz$j;@6;%&sHotHj;0JnA$q&$GItHOvwN^j}0G-Re5JLYpsMa zibo+Au^`Gb*20Pe4skw_%Q*~?^YCD7utp%)5o#1!5;@JP7V#3Mmez%oa2|;q9a&W~ zXI+lpv6iatVI$79q;4cqYsLFe26EyZZyqmaW)rEY)%De%-$yb~uhgG##dEI5Su56; zPG(fiqA@k7*j6+<9tQt|9{4;lDIH2H?3tg&eZfYftkF=Her zl8U+6e&KzgMJrd9Yr7>uL#)#2WEgfAUA=SG(z(L2Mpk|kjJH*)<^PFz$YOO1D|5d2-$eD zAGjTI`gT*CS8N<;2jV^5u><%Va1)UH@SG8zT*hYcE$R3bxDEIn@I@dc58ewMbgxLJ z4juRc@SwzYAVNfT+cv2ffB!U)DhlFg=(_{5PtM9h@E~^h%JwDq10sHmE?f?J) literal 0 HcmV?d00001 diff --git a/ios/libs/libSPIRV.a b/ios/libs/libSPIRV.a new file mode 100644 index 0000000000000000000000000000000000000000..9dfccd970458c064c29eec23c54db1addfa1555c GIT binary patch literal 733392 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

#kbfR@E8SdDIf#Jnv4>@FcX+#?Trs% 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�u%&SqAySB+&{LuQtw4Xux982Xe{$oS1Q&YBwWrI`lZBo<_GE57nc*p0|A+@v z+^wo99^CoRUc@JQurXH=B4vf`v4!?eZhVs&!o(Knk$AF}m1qCt#y3SE{V7*}^5{=) zdtOg=C>DB)Z}ax;KA3dd$So3@uWxHMrw9H=v*-Inh~^g$?t&ck$)i4jR3b7@J>>8Q zNuO+6jogJuFGnl=sUS?cd_5LVHoDk9x%2c4p{HDXx*R=O=*eSG=5g!k@N|v)k3EGM zpm_AHmT@`3MWIVyprToPg)G_@f`er9Wyaf;UE!A%*=n`cT}f=hh_l zU%YQx|HYEH-Vfr~eqglAsd-1}ukWF&gBgk55nz9CDPzMK4p!l0h;!kaw)FME8Em8r zaYJ#eH(g`HmDc!lHUb=zMv-n5&%iN>(hlLB!*?@L>DW7L&0w74fb+focim7mJ2LptU)((S&|ls>)I-mc4h;Pd3R&;TxH-r^XzMH=BaE5n8;kyrH9c1hvFC*DI0v=7`&$C4R`X0I`=mI^mKnwa?syTrm`a+Ph}&O)4d~=iIOIB(LU9z_f$FSeft_g|C30s zVDffF9)c17U2p#)E&lk*izVOmx!BodQ&`0zjpcoaxF0@K(*KsjIZQM;`WN2dprLJE z9v%I5-$L&Q#V;5gtr(gLzSG!2s>ewx6EsL??CgiBd*{*nV4T4H?Wx{=f^#Y^dH-R+ z7$VxMe85@d8$!P1&h&Dshst{rY2W7c5c&I%|Kfe6pzU(dxTHVmTZXpPc-!V{zToR4 zqX%D}?LCs!nLc~zui~~8kBnBl3_5`)jyUtsA131uJmc&P1hwlxGtg6&bqx8^k>}}; zM=OpY57Hhvjk2?lFAMpykT0{dR^$UMRla}zcr@>Y(NRbMw)@GzCpyx|{)IWm0AAznK-W{k%T>r(Nu-*^jG|sn~7b;Kmw|=2KYXR%c(wwg> zI`HSejNkm@_v4HI_5Cyd^Mm)Z?vH;m6W^UbE_=m^XXlSsypoDAWs-L!WimVX@)Y*! zA}!^NH=b1l<5KsJI#PzKf!|R4>wD7vHRZ`#2er%gU|$?NxYEH6p+6_ZgYK&|*G`|7 zI$SgBuJcDBx8fnwd|LAGKqC4j`ufl(qlX})la^{}!$-llF2paT_yiH330`vn&Qie0 z0N*avQilKPlhKMruGjaJeK+OF_o?mTy4F!UoJ0RieU0^lk4I`b4^Usa<~vmjy+7Ux zI4?P_`OZS;!mGU*8CSmp+ylTl6F486gff83!wxobGjKU}e#eO{$h22bXCLZ(X6oK~ zZ%t=sv)nuPfJXaS+JdWHEbBYznrnE0yL%6{1C_sZig)A~@}wirKGcP1bSh5JOE2rf z=%IL&QK+TvR5a`UX!OuOp&n`YrqXr)ZWJRr5__L`pbRbw}(WZ$(+Q_9tCYHK)(*qW3MB5xE6R( z8=nI&rfb@nF5+tmkJ?P7JI%k(fs9Q8UoQjfV&L(UKF~Jl6nLkP(>D1G$(k3@9z!|Z z^8#q+4B5uiE)4DBbg*3KB=)Lv*1*3E#W`0|TV^gewkO@m&a&+8J$uo&wCvq`ma^pG z65wVmON}$eG!F2c=xb)2jPimx1P>Ceh!>!u>{`HBFBFnp%OF1#-Kf6mS)dg6MNSpm&3obcXukQZ0%1 z_rB&aq-`|-Pj7Ptzi)RO)W9-lk#B*`+`{~;&E_QGgcyx!%*MNLI2a=xL zfj%>c{@Z~3k9O7ve~a{wf}h`wo3{S|@*M!4cR&XG4gTKJW(<3Q*EH}bl~;fE{u2iR z^+8Jab$lZjJ$SFfGnKg$eJdL{ba&nmBs@;XB?w&5mlhdtJA?kd8n`{8CG6Y_e5ee9 z|2Lft!T&_QZvda)#!cVqXzAybQ9L>OrbZ?Eq|&lr~c^A_~=r%|V- zWvq9HHl6EcP2j!Npx0Y~L1XAY0mgqGaXtAKXwn5aNA+BS_@8qg4WDiS$$FIeb1i-+ z<*Nd1F^|{Zy@2~7`u8-zY6N``5G=raQI@$MW!`?s_2i4lTZy!_;KhW_#X%?1Ltc*< z#?V)3Tp(IxK#m&u^8m`G{0mSvjl-W;o}@lbd^HiC^vS&A;mOfaEuG!X*xi$U=3tep z8GBB1;^|E-=^Y1qSNjook|E7376jJ>9nLpl=ZJfczVh#h43pBdNx5u3gqgni|K^H6 zz3C?T=Fe;k+>2wlGn%q8{;27XGRP$2uW8F@tlA!E>}bqr>u90FS^YH`l#bah6}Ftf zi3Eo0d(|R*0bP5(NqS@Rb8$;KhH6eNU(gXTwi|z4>Ses&Rlf0teIOnF>9zu82cqx% z2Qp)>i|L>F*N2HH{RZ%dq_+54`K3kV*Wo8kr(CcbK#21nG6R$?|C=b3e&7HTemBbe z*Fsp)??w^W@~@TglTdy*{3@VG($6XCiB#s_-DJqXFINOM_`77hjIib3E#s3SM_Kf6x;ZJ4w zEJA=<`~*UPSX?Q?b7*mx3K#zdA;$E@hvoaT^8IFnl>P!5m*R(H_$EU7z7OGb2pbS0 z>Eaa#!E1{%5$1s&*NSk%dtd{KA3}&vi^=9j@x)gMH*80EJxrD@2U+i0}&tK})s}A!yFOXCS2X1b+d-new|6;Wc749M^>Leyu<^9XYYp8Vb=L#hwOw;-hWO8MO@!weY`o|KO8q;v>) zIg{d&(&kT!d)CqCc+TN;T$s@{bE@OqjNlBX?oKV9>jgtB2&flEc*~KYel+nmG3F?UD5L?`Tn$wUqJPrJisuAcUj`kqb-f`zp%Vhq%oe*G`!zCDpR?dg^3j-{ z7B8!}SNYm&TbsAx<;yhtmjdYdvyU(3UOEerdV(z+X( zHwUnk*V@|L%E3}n%STRXrSQsCKWr~Yavp<=5B#RD9E%VU6P5lbgrr!#Mp~6r2Id zi{DR^`Mg2Ag!vx>WK_SFnmHnqSLXd1DRzdRl|+DN@oO>rq4X(uQdv3%ctpZMOoCBm z+ixsClp$$wP`a0sCQ4C$z%QyF%4rKc*Vyo)`k}lh;dv#YW&$47_jyb{VUM7niGx5hwZ`UheAySn+VO9$NdYpK1}OIw1$*c z;q6b4!@4Wh0=n<<7P-E_=ImVJ?O&>~En8pc-t(mwcJKKX)^#!ENlL3`y)Qb_h6j<> z=@V(=;ZHzmS0JquYviCq5{o0hlT`Q)2;Yc7tjkeeDhGYQmbVOfv7R}6682;&-}T98 z!D-|_6PLDsmF6wF5q~?h#QKvLu||M(t1SFs{pu|FGY~#UVH2;7_l~@X^(+t-Yj(+e zEfIv;T}w9nD%M*&g^f@hf{3F$T_`KunkTK%iFHWxdMIEeo!|UFu{NqH2t=uX%Xo1mSZlbX{My zkD%#t(53`5S_WDb_n+VV4}9%XwaLZ%?D0g~(Vt9y^+NM3q@Rs^bC5p?aFRje6s$2% z?)?a~{V>kCf9M+4JLjm@n}jtlOyT)DsSEAv)U@8ArEKK%RPylxJI_ z9dXWK(7pmg#;%VYtQY-vS6Uo=Uw{|!{6@JRTr1nM?vF)ZDt_U~JsZ*Xgwsjz^+K$v z(DQx3=NR~f;1YlT`kCS}%Q!WWGRW6Nm9em7%rX|rb+vKT<7z`0&nzFaj8l>Z<0@lO zsEi@>Wz}}Zb}gg!BVIro4(&Z!RLg?-gExeHd5G?ccQo)3wH+=`yTMyp56FgV} zUMvSsuIsf;oSEq3p&3dXi|B-qKSa7(sG)h4+)wGe=wqr)nCHu2SRIz z&Ij%Z&SB0T1&eSBI22BE!r(NA<5c_A@!@2|1$ZV|aiOuzh{I<^mvFdzmUIzqW^OCO z$-2g^XyYsvJ|@n)j~4Z@V1a07;af)eDiqhuBrjh;- zKfDoZ(eXE;&%zI*e$p3O_u<_)iEXLE*uJBRZCQXYk##*rGMQ;{2bku-pN2nnAhDRi zN5S`c8P>TInAV$!x~xXo_3&M|K}$IPlE!jDGIJ1xE#l~#N6Wk0|s2a zi*o(}-`|G+=>ji&JOwpN{uD<(x92x&kgs;XTPi05 zk!RY%u0?E*iKG1%!{?3!{yE44}@E<(xg#Ymw ze5>8(eIlA9aw`;uVcUJ z6GGn)O{3_miyhr-cuQbiIh{`eQS{LuT74<7cJ(r`tCD60r7yc9B7mg(%v_l97 z>VN!Q>T3GCr!dDN8m6MW!Xar$A>Nf;mv3bA!%436Z^El4fFtLB|E!MvxuJ{MEhk()#0yfPb z)I4x$eL>+0-$2o6%o)=$52yLj0?aea_+ZW`+mzBe9l?V1xYXfd@Wktmk=kL58n41INz0=tUmI{*wQ5MmVU@+Lcc2e90f*!p!LJzqXwJV8xH&QY(flwK`yM+D8DERPdbG*A z_#=PSu0P*#pz_a`9;knS^*(~X0}rsXRj@($ApbP%$G8o6rDFU~#@K7c;U$zqIMl*+ zqHypc58;6IUlR^*Bh7emc*_w#Tm>G3eJJS|@J-@;B;;qeqxc6~pJDx#4mLvVK=oe` z9Icp*v}9)?xwa_TTNt0r3SV@%xZffM*O=gF=dq^*`Qgu6fofr=MXz-2;vJqb5AB~3AMTB z9NJSFec>PJJNej=C-!d5`L2UKrM)X+MxQL!@-q{kb7*%bKIPDAGahkh&uK|`{EarL z+o26=H88R|CjG*JZIJL$dd)HE9f$U&12#MbTEM2lhP1@@9PAv5CRA9(vgH}d?9R8h z-ju=O+3n)Q7hBA>s@5j#KSUb76pE03E&Ttn|JyYxekzQVgKUfRQ=yl?F{Z-HU7iI0 zxd~RFX<)yHs%QSuclzCp5aw1}Jo!PX!Ki)KUBe1eua!D#KXluA>+wU3qM&~{>=aT5hly@lYC=~ ze@(_y`S{u5$={BClD};6yJh^>1pRgTz6pUuziZL==+}*SkV21tPsTqtO~lt)@;l{v zM3VGl*=31eE#se^De@EM;rL@8%DEB#YReI>M0jDA2%kc}MR?zhunZw>ZlUl^l(z=q zL4=f^Z1`CSod_vCG1+Q_=itaf;d=;|Ate8vRS3zCCkNpG!eWHG z??XuVXCS;4;e3RIUn0WQ2%Yl%Ml4YLG2SO3%tlDYG=fk5l}i!Acb>o3BE%XC+Gr+$0fhxPbmk zaDyV;Fo=-g{R|<&8$d|#ek8&ThY=FI=MfUT-3STZE)j0nj_`WCV}A~X8=x0(c!dZF z-i-(eUZw~)T#Jz4%|}S^7(#+~VKNUlkl*O_c*i;ohlk;l^TCf0mLmN@gao$_A;EoC zgd6rDB)Cr?B)B&sEJb)NLQ0>8kkTiKaKlW5l-`Mu(hp7&{=7d$xB%~mW%!f~A3=yN zx4K(|w|osDvaaqD;VqR2DPM&Q3uTyzkn&wC!do&B;@|4|BE01Sge2vAPlm6_ko;gN z-+%~j`4K|=TYXrBw>*K6@;xF$I){MXD-lw@yG3}*T?jS2SBUVI8xdXyI?(ulaKp6- z{}lNMIMMwAG9%nTZvG|sPJXu6;QN~*+^`SfLVRD1kow&(0Q?Sw%MsFdnoQF7uOOuF zh4_wjjOp13Z$_Aj5Nj3FGZ4c5F+B|-`OVHm_$LUR2ya11NW&;Ho#3HMO@9v|Wcu_W zgf}4^L|BOMO@vstoBj)g z@_U915pXz8$D5OXGZ_xNle?xk9eq=tn=;k$n<<0%|FtP^;{SoEKb<<&ad_&F@c*;U zKIc@&Q_g+(zuWbQYpSEm^);8%u{-{Wc&FppguVp8N$5&+ItCNo!E;~Yb9ml0ZTB>% z<6L48&p(`9Jon9b4vxc*%-DthUz_nJ{@*?G3AhixGjj<4 z@1Fm}{HYk1$ZuEu>ZafwJX|Bk$svp<^uArb|4P2!E8h>x_s8V>x8(a%^8FOOgJ4Q; z`rnp!@~fxvmA>&^8L#w!`{lbD_iN<48s}HZcQvjbrFR4Vn6Gj_V&$hm<0|}IWeghjQ-tc}8#bXRmegOYEjr@8Q^%$#{?LDm45hNfRm1Qr4Riab*Ffx zf40l?N}uhL@RWXa1M*XPrH^G|{GTytfTdw_NWWjncP#ku-?dbK#MjFBM`gUC|Glz& zrQebqC-`@vT>6!Q-h^)&^3ksW?*{U+AK=CKzQyv6^*&R)8@y*s|4j?Lf3v)Q5A`*s zueQLW@xT~giuxGehb{3(Eak7Uygy@s-;6pN;iXSCzn=u1jPV;R@$Vzj7=N7wpZ~O! zKNEB|rl;}H_>M8(^o}vd^iG3{G5y09_!MW1Cq2RV{(Vb%q~06jJ1zBHU}>*h%lldM zPhnSzKw26+5vW9uQc?pz${THMfpi=*0b4NRLXTY1Tb@E%{`IjE@_6uHFe zL;x@ltg*4Vsf-_#PVSh(ZN9~w|zbchI8>{?D&A^wskg{a~27j1e)6-u!Lcc0I{Ikdcr&RD7Ku1TWZY|YR0JS zH^FRh_cr#D*ie-B@me+}$Xf{1*NUy#z9vsDjAN0WjRib{zeQ8 z`bHYORyVc~&CDB8z|%flj_sq4i*wL0Y_$2ebog-zczEW*Ma0z6Ev=-k$}SLBWt(=q zgsKs>%ja)zgFI_0U0dB?Y}r_Iqplc|CYpPD8)$&CS4Ap(e7s%I=J(e(Z`xG49kkNr zHUC-@Xf3TXR8Wu2t8VaDnd97{%1@yDmgY9P2P}6J9?HxYotQ9~a4Ch&xSxX$>j6WB zCJe5qWg~7rq>V$R1dngI+UVaLXu?SV?bWsF6OIHoe86?}7{IY-3kN?+T?#DU(6F^} ziSp3)`R){F`>pf0;qF`&?Qh)Zuc`6ZENSG&)f;Otq5HwHM~aR~zX{*u7SCYB?fo zCwbc-$8wIgIPzFOZ(6*%!55JaVaD8>&K(vzt}^(~{w%)e`?2yoIUbxpoRLu(U*58n zZjCV=IUH_ZmKQc3mVrO~VAEz~i;whkJ}qYRm6QiR^$xQKt=sW^GW0#xeOUwBL-1g# zV71@X*jEXVZC@77r^cqyhC+f)@XhD>DmY{xr(eeX8kzp}pF~%GAM5<$mQI0JP};qI z0eFO8q@R6XmKncV+5nGV7yln;I`13{o~$pJlYZ9vz9-?$ln53=vN7NM8CUEYMdwdN5g-BC+1u7n-#yzZUJb$jPHI#0+#PqTKar7Rqa)w z0(?F*eq9n?hDss)>ZxAx`iD41kkD=PRfE7ZSt9M~Mkk+BuCkb$6nJ)!u5}*Y*VB z>F<~Lt3x)dJB|B?(y{+X_^)eDb|ig1{5zRel+Jyj+5YrtlY`t}e4y)QHt@jB=>v|S z^I8VqHTaKbblsB427c*WfjkxDJ5A~1gU;1##PK{kB4ESEjQr#8Mw%}CWlSnczc8ym zeK(%JlGLC66v3KufE9M#!Ui6_**UPR(>XVFwrk(y-VFGqXTU!_1Agim@K?{!CgE=~ z{-zwrDC)XpX(xP!amKQ%(s3kypR3o4^koa!5!RJ-!1X-74aVbJ+yO80djW^yU4?N+ zTp81P)BCiM^k=mZ*FJ3|?m0Zq)Q+U@0#4Zo_aUsDT$J9&Mw|nV&h)#rBLnb3r8Le* zP#>Aj`4pZhEz(hXg}X6NxIGm~uX*7EoivQK;);gZI6L*?@)KDn?|*D3{GiLomwB%D zu^W;TdQQV9Z1LBZ1)tLrd%lh|2ax9Lb&bJC5dU0qVh^1Q2pUz8FWv3P*QiZ9{^Dfs z*<$$9t@^q*Nb$744|@wo$mckH8aqp8c6K?0?_urh-hSExMrT?AAMTf&j&qT*2eBd@ zdjl(xmfounI%jsRLwhC#p22=O1H5P8d;cMPM4isAb+z!lrZY?TQ5iTx8O*r*Mbz_Y zzzaO%?RUWkegJM>SqtFjj{O2<({NtyG*?e8{1GdGlNbKHlt=hMhRzEm+Q&x6TTf*D z%0R~jpyMC$nmJuD1U+hU&h6hS9(ipNJ5>2-@yL!xHN9_CK9kVP z+vQX|58KztbSsf=WhhH9)_UugKAg7nx&&@rzV{=n$7 zkWJ*he77-d(;WaM! z9n)o9A(N<%SV~Na2^R9VPnWPh@d{Xu3Bp4Dc87%ZzJ&D=`DCLF#)}v7w|^w)-2NXD z)|m;yLjLwM64t*+SpPObSjgZ0ZxYteC9Gdg5Ek;c|5CzwNy7SH6NH8Q?f*-{`k{pN zcN2t#{Ox}yU{!uc%FJiv`=j#xG4XEHi)!y-Bb7}uzE!5*DBm}!cSmp4Ixpwl%0HEH z%VeBKzURyLg<5abB9XTC@5Nq$%IV@g+_;K98TLHi(Gt4P!M;zQ&cvrZBrIO+^CDk( zC-$a1d>(fXOlGqlKF^N81z;EL*;)y`56>em=#^Mz-j$(wFR}r4f$Ni958TYU9>m{6 zH>Y3AMn1~n=Y1!A8~Y6ZHpN@`MhYv$TKBBlzV1{e=^fBhw$ziJ zGL3Ed8Tv~A-?6u3m4@>T)IJ?!zOC5L^C9|r-=nt&`=?-Eq2@fki0*^H{)2A7d3hO| zMSJyL0;~mE{BgCvsL$c$`}70&?t;$pFxqNPXMPa%AL;(yUH!Bt(1HA;c%Sp!-$BT=);fAIqd5_@Ek#*Geq+3O5>vM9?&PRatv8~NRd!n6RVc6FO zy=EqKZ`xaGY1@U_w~ggI^vzv5qd}a^=zaAbV;Xx8(64Vw^%l-cHOodyb25SGBIq2OY)s=cH|C?eb&g&CB~u?vg)BRU zaZU9DCS}>cGn4f`sN%XTePjfEHi$NMe&hC_3wCtT_H{;M?3g90|S&ET&gujGC} zvG-E$(?i>i*5ykc6uKpd4|x1;aEBAHaV5&PMgcO+j+I{xM-%f3l_truPV>WM|TU&)DY zXZ~x)4}7lf;W)?`=f&c0(s)+n?%spViU%`Czj~q;ZA-jAmjxfo`1q?Q=$UAFK0d7{ z7(ch?&fC~w+5`F5z(MV2Rc9A%JEQe)$9%FKFq8~Z_`zIRQTY<~KTl>az}Fnd#lH90 z@CQ47kae>2L?X`Mc;w&jeT?o!co_Sf(_zmje&FFfRCX=opbKMs0CFxc4`(1;EIG0A z-|v6y2K2jH+*fi#pe|U8`(`o&i-J~Jt(iuRwF9H2s$yw?*-H^YeCw4>rTIDUy80R)f z7ESN8ltW{pYo91uLK-7NmX9qK~EVF<2f6(=WIFEc9Lbp63hAIG;i8V^2dreUaN21TSzsI0hXn{C;S*Kc7LDM4KgJ zGc4NlRhO20W*_!4e~hu}Mcg|DSy%B&{6Fvc(yx-AtV4TNbZ!eC#QiO0@@}q&!4HdY zUkRPJwtUu?_}yF&&-Na{dws?{)GtzIGK{4d=f0r@)4$^APrr-x*J54=-q-Kx>Hy4V z!rs%h&2~>$pS-7QKkDy8{pp@Ax)*A!d%EbpDWVzhJwyG2=ye)$n`jq6y)r?oWAdJ^ zR4rwvqF*lV>G~PkkiMyO;qU1xFx}JDkFu7ctS*#AG^$3ZXyl~v9qp8gc2Y27xu>fO zV_~>`)WlZ|x<@7Ykg`{)@ya+}$12CZbw!R{kzXDv>v86bZEU(SZeAHT<@`F< zadRww`v`W4k1;PMc%-kT;k=umMUQfV?_h_cHN_KTqwB#Kk%V!aZ0y*(+Z!$Y-j_0m z<6)DqrNR8g+1Va+O{4MGdjxl5)<2E)$1L1eN@H&^p65bOYeN}IN2IZ{R_chgVRS?~ zA13n~>@dcXUD5PJI+v2>2}WCs6+ffyH~<|2W4uXsyw;!}o`-%|7K48HC(sYCf__+Q z&=0SIepqSH59dQSoHygDp54*(!&cV+cNYEd9CSh0bVdRe{V)l0{@O75VPy>ZVSXIh zSLr;$OS7*AFy~K#eKiB{!p*fWhkiI3r@b2P&R60Y#XrR3YL21i7c|#UHl0}J7|Q1P zS?l9{(3O-u`xN-mYR@L!8?Gk0orP@LWRoMiwoyLtwu=hFCyvod<4rvHf;A8lzkZ*Mn@k4c8{F;yQQ|Hi=E z#Cw-#d=&OlS}#*$WgqH|GoYm%N7S2awaUIiV`Lu2$YavJat!vB>w()Fm`CD{=i^t6 zmV7fH$H=-_WJ5{SZ7Aq}Bf?fG>?k*5oW$8K2fGd9eH{(2L}$Um7ezvoVj zlh_w5?I?5>9G$Z+?8CpRWBtFzI5~oO;5Kec5##=c5yr~oOBgE)Ft&Y!vGN$k%9lZd zkbOLLcnGrlv|Ni^h-V?Y1r3jZKFOU0!MzS`3qu^vtI%aQjhia&X`G364)7nJzA}jQ zv4iaoI(qxAh8@Dqwj>~5AK*CoI#V(~7hJ`yB>%6)IO`Q@$d{x0QEzYvw4k%$RGI{& zc@Oh>T1)K)oE2C%Vs!2y*=A`ia6UVdj&;FgC)Um!&@=8pS&*MAV56wLgN-~uWdm;x zpYp?APw?iV4}1&ZNwim`T=TA7kF>CJ)UIbEvFHP8ZR~RCyXw41>dS9{r$4svw5cyc z*F6s1mCmcQrQ`jxgZEFY3qfa1svm%T{t)zGTUvwu{37(>zlLtBbds_9?0L{`MNDIp z=(EvjSFZsK=fzMzy&L_M#((OofWg-l=-t|1 zsZSQlKAVg_i*tw1_CRKc^BYCK{MAO$Uq9`>`la7jUqwHR*jEw9`)XE{zDoI{^wkxY z*jJy3(pSAP=>F^U>CpdP!x1Z#5*2QHfmP(%!T0hb{w;fhK zA|In48`F)xlr>DW?^+h$dknT2ta%?f2|pH+k;Xn2ZXBe!q8bP1VH{L*#rOpCIA|OL zX|DL|D04*`18>G$k;cKtqm6->EB*_{KvSQ>c-w7VOTaf8|8VRh<_#8K7n&=^iMpz| zF7$Qd8tC6*{_zpUk8tB(0R5cCWz4yf)Ht{ia@9HxJ`ET&-qF1L6vjHD?LK@PYtEPj zd8+(){zHyCM-ZC$QP#cwS87I=j?jI#& zI^`Lkf0W1v97k%e-w^Tvz&p1GoU!{eRW2O6jje013vrkIU#^)^W@_ zE+=5^(5PcaO%EM=C-}{lM(No7#r-Qa*YTB*2R;|u@&Ncr*rbx{7vNdgq>}27;tcvZ zF7FZS%}7%I3tea%;!~0Vv}Yn2YxaYG1-}^h#4vehh%(*KGLkd0ii0fuZ+ zFNLv58U21f6C2{T|HT;4>o zdBZ0VvgWg~d5g7oD}GmOSO0g}u0Fz9{U3wZX+8!6i@wJ5>;LD$b-&Z+y&<0*;~LK@ zjIYKuo@nWb-(SJ_YD;6|_qp7LwFqlGJ}r&&`yz~|wDxlnV{6tlvG(%-o@q|niE-Ab zZ$-0h#Xe8QT?BkQB|lqXClc#G_BA1Eea6#2V)Yq{ZB2-LhQ?kKvib~t8f!x9F%P_) zYeKQiD<|qRG}hV$jR!Qpq%k25KGL!B8qK|8TW1twgWxaG&nhwAbkqD%_CMl9BVTpF zhGbo9T#0_rj(p!X>BVwxV6ZLG+U)SiXav1DOnT_Wb-4E+q!+9C25fYlM%#0W!S);) zr;I*wSJpt)d{(q`AMBu?x&Cuy4fOZ425R=9$c63vT(t2OYefHuer}w0mKd(B~k7Csa&<6fu+%x8NrpPhy~(hgwn(*Zmmn9RQTqLxrk<7)!!U61_v zvTv@O#d>j<>~K8nx{V)x^~91u&mNuE-c*h zb>Gzfi|`#DiJOXXdJ6Q}$@_mN_p)8U*qx6t@tt2gvdA7c4{JInt7*@XxG&0Nv!HcZ zOP~AbD%fx%rKfdS^f_A^Wi!(KmgXCDS}`^Xo%SlO(=LKeJDf^7ZbE$(`rV>gLf_Ts zIhmg4)Ia?@=)QBQ|IV#1#&Zh#T8|^7`;xD4G@Ccso{l{li{I0Hsr!<@xfrJgp#z_c zyDIb@xC;H4zAK$L4K$~HTIvo|iW7QtCh0O3I#S

%xQRdxcmR&V;WC`Q2j=+sFmj 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

KYo!uugWZbfj*0_#l;-Aq+R2jn0(FaxO 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�@?rQx>RpQ89hCilC1l{QktFnXK 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

{k5$0^i_Zp`5mPJu$7tWOgw0hM0>OEZwFtV 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ǐ!s8 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%0AxcW3u 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%0ABw&)3EOC=~yFQ0!`;q@xUq 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�Y$tL#=-3p~gS5KEf6AQ5n_ysD^6k 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 z%0A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