From 48620759765d10116703f45d35f3d418ff80805e Mon Sep 17 00:00:00 2001 From: Triang3l Date: Thu, 8 Oct 2020 23:05:30 +0300 Subject: [PATCH] [Vulkan] Cleanup and update SPIR-V dependencies --- .gitmodules | 12 +- premake5.lua | 1 - src/xenia/app/premake5.lua | 1 - src/xenia/gpu/premake5.lua | 5 - third_party/glslang | 1 + third_party/glslang-spirv.lua | 54 +- third_party/glslang-spirv/GLSL.ext.AMD.h | 110 - third_party/glslang-spirv/GLSL.ext.EXT.h | 39 - third_party/glslang-spirv/GLSL.ext.KHR.h | 48 - third_party/glslang-spirv/GLSL.ext.NV.h | 54 - third_party/glslang-spirv/GLSL.std.450.h | 131 - third_party/glslang-spirv/GlslangToSpv.cpp | 6146 ----------------- third_party/glslang-spirv/GlslangToSpv.h | 67 - third_party/glslang-spirv/InReadableOrder.cpp | 113 - third_party/glslang-spirv/Include/BaseTypes.h | 387 -- third_party/glslang-spirv/Include/Common.h | 274 - .../glslang-spirv/Include/ConstantUnion.h | 625 -- third_party/glslang-spirv/Include/InfoSink.h | 144 - .../glslang-spirv/Include/InitializeGlobals.h | 44 - third_party/glslang-spirv/Include/PoolAlloc.h | 317 - .../glslang-spirv/Include/ResourceLimits.h | 140 - third_party/glslang-spirv/Include/ShHandle.h | 176 - third_party/glslang-spirv/Include/Types.h | 1924 ------ third_party/glslang-spirv/Include/arrays.h | 329 - .../glslang-spirv/Include/intermediate.h | 1486 ---- third_party/glslang-spirv/Include/revision.h | 6 - .../glslang-spirv/Include/revision.template | 13 - third_party/glslang-spirv/Logger.cpp | 68 - third_party/glslang-spirv/Logger.h | 74 - third_party/glslang-spirv/SPVRemapper.cpp | 1479 ---- third_party/glslang-spirv/SPVRemapper.h | 304 - third_party/glslang-spirv/SpvBuilder.cpp | 2676 ------- third_party/glslang-spirv/SpvBuilder.h | 641 -- third_party/glslang-spirv/bitutils.h | 81 - third_party/glslang-spirv/disassemble.cpp | 695 -- third_party/glslang-spirv/disassemble.h | 52 - third_party/glslang-spirv/doc.cpp | 2894 -------- third_party/glslang-spirv/doc.h | 262 - third_party/glslang-spirv/hex_float.h | 1078 --- third_party/glslang-spirv/spirv.hpp | 1028 --- third_party/glslang-spirv/spvIR.h | 407 -- third_party/spirv-headers | 1 - third_party/spirv-tools | 1 - third_party/spirv-tools.lua | 76 - third_party/spirv/GLSL.std.450.h | 131 - third_party/spirv/GLSL.std.450.hpp11 | 135 - third_party/spirv/OpenCL.std.h | 272 - third_party/spirv/spirv.h | 871 --- third_party/spirv/spirv.hpp11 | 880 --- 49 files changed, 35 insertions(+), 26718 deletions(-) create mode 160000 third_party/glslang delete mode 100644 third_party/glslang-spirv/GLSL.ext.AMD.h delete mode 100644 third_party/glslang-spirv/GLSL.ext.EXT.h delete mode 100644 third_party/glslang-spirv/GLSL.ext.KHR.h delete mode 100644 third_party/glslang-spirv/GLSL.ext.NV.h delete mode 100644 third_party/glslang-spirv/GLSL.std.450.h delete mode 100644 third_party/glslang-spirv/GlslangToSpv.cpp delete mode 100644 third_party/glslang-spirv/GlslangToSpv.h delete mode 100644 third_party/glslang-spirv/InReadableOrder.cpp delete mode 100644 third_party/glslang-spirv/Include/BaseTypes.h delete mode 100644 third_party/glslang-spirv/Include/Common.h delete mode 100644 third_party/glslang-spirv/Include/ConstantUnion.h delete mode 100644 third_party/glslang-spirv/Include/InfoSink.h delete mode 100644 third_party/glslang-spirv/Include/InitializeGlobals.h delete mode 100644 third_party/glslang-spirv/Include/PoolAlloc.h delete mode 100644 third_party/glslang-spirv/Include/ResourceLimits.h delete mode 100644 third_party/glslang-spirv/Include/ShHandle.h delete mode 100644 third_party/glslang-spirv/Include/Types.h delete mode 100644 third_party/glslang-spirv/Include/arrays.h delete mode 100644 third_party/glslang-spirv/Include/intermediate.h delete mode 100644 third_party/glslang-spirv/Include/revision.h delete mode 100644 third_party/glslang-spirv/Include/revision.template delete mode 100644 third_party/glslang-spirv/Logger.cpp delete mode 100644 third_party/glslang-spirv/Logger.h delete mode 100644 third_party/glslang-spirv/SPVRemapper.cpp delete mode 100644 third_party/glslang-spirv/SPVRemapper.h delete mode 100644 third_party/glslang-spirv/SpvBuilder.cpp delete mode 100644 third_party/glslang-spirv/SpvBuilder.h delete mode 100644 third_party/glslang-spirv/bitutils.h delete mode 100644 third_party/glslang-spirv/disassemble.cpp delete mode 100644 third_party/glslang-spirv/disassemble.h delete mode 100644 third_party/glslang-spirv/doc.cpp delete mode 100644 third_party/glslang-spirv/doc.h delete mode 100644 third_party/glslang-spirv/hex_float.h delete mode 100644 third_party/glslang-spirv/spirv.hpp delete mode 100644 third_party/glslang-spirv/spvIR.h delete mode 160000 third_party/spirv-headers delete mode 160000 third_party/spirv-tools delete mode 100644 third_party/spirv-tools.lua delete mode 100644 third_party/spirv/GLSL.std.450.h delete mode 100644 third_party/spirv/GLSL.std.450.hpp11 delete mode 100644 third_party/spirv/OpenCL.std.h delete mode 100644 third_party/spirv/spirv.h delete mode 100644 third_party/spirv/spirv.hpp11 diff --git a/.gitmodules b/.gitmodules index 6c3ca7278..c50326cb4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,9 +10,6 @@ [submodule "third_party/libav"] path = third_party/libav url = https://github.com/xenia-project/libav.git -[submodule "third_party/spirv-tools"] - path = third_party/spirv-tools - url = https://github.com/xenia-project/SPIRV-Tools.git [submodule "third_party/catch"] path = third_party/catch url = https://github.com/catchorg/Catch2.git @@ -25,12 +22,6 @@ [submodule "third_party/premake-export-compile-commands"] path = third_party/premake-export-compile-commands url = https://github.com/xenia-project/premake-export-compile-commands.git -[submodule "third_party/spirv-headers"] - path = third_party/spirv-headers - url = https://github.com/KhronosGroup/SPIRV-Headers.git -[submodule "third_party/volk"] - path = third_party/volk - url = https://github.com/zeux/volk.git [submodule "third_party/discord-rpc"] path = third_party/discord-rpc url = https://github.com/discordapp/discord-rpc.git @@ -64,3 +55,6 @@ [submodule "third_party/DirectXShaderCompiler"] path = third_party/DirectXShaderCompiler url = https://github.com/microsoft/DirectXShaderCompiler.git +[submodule "third_party/glslang"] + path = third_party/glslang + url = https://github.com/KhronosGroup/glslang.git diff --git a/premake5.lua b/premake5.lua index 2b8042334..40ecf8a92 100644 --- a/premake5.lua +++ b/premake5.lua @@ -225,7 +225,6 @@ solution("xenia") include("third_party/mspack.lua") include("third_party/SDL2.lua") include("third_party/snappy.lua") - include("third_party/spirv-tools.lua") include("third_party/xxhash.lua") include("src/xenia") diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 3a0f6bb2a..e260449e9 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -19,7 +19,6 @@ project("xenia-app") "libavutil", "mspack", "snappy", - "spirv-tools", "xenia-app-discord", "xenia-apu", "xenia-apu-nop", diff --git a/src/xenia/gpu/premake5.lua b/src/xenia/gpu/premake5.lua index 92f798458..f4b2a08d8 100644 --- a/src/xenia/gpu/premake5.lua +++ b/src/xenia/gpu/premake5.lua @@ -11,16 +11,12 @@ project("xenia-gpu") "fmt", "glslang-spirv", "snappy", - "spirv-tools", "xenia-base", "xenia-ui", "xxhash", }) defines({ }) - includedirs({ - project_root.."/third_party/spirv-tools/external/include", - }) local_platform_files() group("src") @@ -32,7 +28,6 @@ project("xenia-gpu-shader-compiler") "dxbc", "fmt", "glslang-spirv", - "spirv-tools", "xenia-base", "xenia-gpu", }) diff --git a/third_party/glslang b/third_party/glslang new file mode 160000 index 000000000..2067d1a93 --- /dev/null +++ b/third_party/glslang @@ -0,0 +1 @@ +Subproject commit 2067d1a93e6edc17f2a6b7e3e5138a9bbcd35ef9 diff --git a/third_party/glslang-spirv.lua b/third_party/glslang-spirv.lua index 77895361b..b5cdf15ba 100644 --- a/third_party/glslang-spirv.lua +++ b/third_party/glslang-spirv.lua @@ -11,27 +11,35 @@ project("glslang-spirv") includedirs({ }) files({ - "glslang-spirv/bitutils.h", - "glslang-spirv/disassemble.cpp", - "glslang-spirv/disassemble.h", - "glslang-spirv/doc.cpp", - "glslang-spirv/doc.h", - "glslang-spirv/GLSL.ext.AMD.h", - "glslang-spirv/GLSL.ext.EXT.h", - "glslang-spirv/GLSL.ext.KHR.h", - "glslang-spirv/GLSL.ext.NV.h", - "glslang-spirv/GLSL.std.450.h", - -- Disabled until required. - -- "glslang-spirv/GlslangToSpv.cpp", - -- "glslang-spirv/GlslangToSpv.h", - "glslang-spirv/hex_float.h", - "glslang-spirv/InReadableOrder.cpp", - "glslang-spirv/Logger.cpp", - "glslang-spirv/Logger.h", - "glslang-spirv/spirv.hpp", - "glslang-spirv/SpvBuilder.cpp", - "glslang-spirv/SpvBuilder.h", - "glslang-spirv/spvIR.h", - "glslang-spirv/SPVRemapper.cpp", - "glslang-spirv/SPVRemapper.h", + "glslang/SPIRV/bitutils.h", + -- Disabled temporarily until PR #2417 removing SpvTools.h dependency is + -- merged. + -- "glslang/SPIRV/disassemble.cpp", + -- "glslang/SPIRV/disassemble.h", + "glslang/SPIRV/doc.cpp", + "glslang/SPIRV/doc.h", + "glslang/SPIRV/GLSL.ext.AMD.h", + "glslang/SPIRV/GLSL.ext.EXT.h", + "glslang/SPIRV/GLSL.ext.KHR.h", + "glslang/SPIRV/GLSL.ext.NV.h", + "glslang/SPIRV/GLSL.std.450.h", + -- Disabled because GLSL is not used. + -- "glslang/SPIRV/GlslangToSpv.cpp", + -- "glslang/SPIRV/GlslangToSpv.h", + "glslang/SPIRV/hex_float.h", + "glslang/SPIRV/InReadableOrder.cpp", + "glslang/SPIRV/Logger.cpp", + "glslang/SPIRV/Logger.h", + "glslang/SPIRV/NonSemanticDebugPrintf.h", + "glslang/SPIRV/spirv.hpp", + "glslang/SPIRV/SpvBuilder.cpp", + "glslang/SPIRV/SpvBuilder.h", + "glslang/SPIRV/spvIR.h", + -- Disabled because of spirv-tools dependency. + -- "glslang/SPIRV/SpvPostProcess.cpp", + "glslang/SPIRV/SPVRemapper.cpp", + "glslang/SPIRV/SPVRemapper.h", + -- Disabled because of spirv-tools dependency. + -- "glslang/SPIRV/SpvTools.cpp", + -- "glslang/SPIRV/SpvTools.h", }) diff --git a/third_party/glslang-spirv/GLSL.ext.AMD.h b/third_party/glslang-spirv/GLSL.ext.AMD.h deleted file mode 100644 index d4f57efdc..000000000 --- a/third_party/glslang-spirv/GLSL.ext.AMD.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextAMD_H -#define GLSLextAMD_H - -enum BuiltIn; -enum Capability; -enum Decoration; -enum Op; - -static const int GLSLextAMDVersion = 100; -static const int GLSLextAMDRevision = 6; - -// 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"; - -#endif // #ifndef GLSLextAMD_H diff --git a/third_party/glslang-spirv/GLSL.ext.EXT.h b/third_party/glslang-spirv/GLSL.ext.EXT.h deleted file mode 100644 index e879714d0..000000000 --- a/third_party/glslang-spirv/GLSL.ext.EXT.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextEXT_H -#define GLSLextEXT_H - -enum BuiltIn; -enum Op; -enum Capability; - -static const int GLSLextEXTVersion = 100; -static const int GLSLextEXTRevision = 1; - -static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; - -#endif // #ifndef GLSLextEXT_H diff --git a/third_party/glslang-spirv/GLSL.ext.KHR.h b/third_party/glslang-spirv/GLSL.ext.KHR.h deleted file mode 100644 index 2eb10ae62..000000000 --- a/third_party/glslang-spirv/GLSL.ext.KHR.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextKHR_H -#define GLSLextKHR_H - -enum BuiltIn; -enum Op; -enum Capability; - -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_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_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"; - -#endif // #ifndef GLSLextKHR_H diff --git a/third_party/glslang-spirv/GLSL.ext.NV.h b/third_party/glslang-spirv/GLSL.ext.NV.h deleted file mode 100644 index c01858be4..000000000 --- a/third_party/glslang-spirv/GLSL.ext.NV.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -** Copyright (c) 2014-2017 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextNV_H -#define GLSLextNV_H - -enum BuiltIn; -enum Decoration; -enum Op; -enum Capability; - -static const int GLSLextNVVersion = 100; -static const int GLSLextNVRevision = 5; - -//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"; - -#endif // #ifndef GLSLextNV_H \ No newline at end of file diff --git a/third_party/glslang-spirv/GLSL.std.450.h b/third_party/glslang-spirv/GLSL.std.450.h deleted file mode 100644 index df31092be..000000000 --- a/third_party/glslang-spirv/GLSL.std.450.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLstd450_H -#define GLSLstd450_H - -static const int GLSLstd450Version = 100; -static const int GLSLstd450Revision = 1; - -enum GLSLstd450 { - GLSLstd450Bad = 0, // Don't use - - GLSLstd450Round = 1, - GLSLstd450RoundEven = 2, - GLSLstd450Trunc = 3, - GLSLstd450FAbs = 4, - GLSLstd450SAbs = 5, - GLSLstd450FSign = 6, - GLSLstd450SSign = 7, - GLSLstd450Floor = 8, - GLSLstd450Ceil = 9, - GLSLstd450Fract = 10, - - GLSLstd450Radians = 11, - GLSLstd450Degrees = 12, - GLSLstd450Sin = 13, - GLSLstd450Cos = 14, - GLSLstd450Tan = 15, - GLSLstd450Asin = 16, - GLSLstd450Acos = 17, - GLSLstd450Atan = 18, - GLSLstd450Sinh = 19, - GLSLstd450Cosh = 20, - GLSLstd450Tanh = 21, - GLSLstd450Asinh = 22, - GLSLstd450Acosh = 23, - GLSLstd450Atanh = 24, - GLSLstd450Atan2 = 25, - - GLSLstd450Pow = 26, - GLSLstd450Exp = 27, - GLSLstd450Log = 28, - GLSLstd450Exp2 = 29, - GLSLstd450Log2 = 30, - GLSLstd450Sqrt = 31, - GLSLstd450InverseSqrt = 32, - - GLSLstd450Determinant = 33, - GLSLstd450MatrixInverse = 34, - - GLSLstd450Modf = 35, // second operand needs an OpVariable to write to - GLSLstd450ModfStruct = 36, // no OpVariable operand - GLSLstd450FMin = 37, - GLSLstd450UMin = 38, - GLSLstd450SMin = 39, - GLSLstd450FMax = 40, - GLSLstd450UMax = 41, - GLSLstd450SMax = 42, - GLSLstd450FClamp = 43, - GLSLstd450UClamp = 44, - GLSLstd450SClamp = 45, - GLSLstd450FMix = 46, - GLSLstd450IMix = 47, // Reserved - GLSLstd450Step = 48, - GLSLstd450SmoothStep = 49, - - GLSLstd450Fma = 50, - GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to - GLSLstd450FrexpStruct = 52, // no OpVariable operand - GLSLstd450Ldexp = 53, - - GLSLstd450PackSnorm4x8 = 54, - GLSLstd450PackUnorm4x8 = 55, - GLSLstd450PackSnorm2x16 = 56, - GLSLstd450PackUnorm2x16 = 57, - GLSLstd450PackHalf2x16 = 58, - GLSLstd450PackDouble2x32 = 59, - GLSLstd450UnpackSnorm2x16 = 60, - GLSLstd450UnpackUnorm2x16 = 61, - GLSLstd450UnpackHalf2x16 = 62, - GLSLstd450UnpackSnorm4x8 = 63, - GLSLstd450UnpackUnorm4x8 = 64, - GLSLstd450UnpackDouble2x32 = 65, - - GLSLstd450Length = 66, - GLSLstd450Distance = 67, - GLSLstd450Cross = 68, - GLSLstd450Normalize = 69, - GLSLstd450FaceForward = 70, - GLSLstd450Reflect = 71, - GLSLstd450Refract = 72, - - GLSLstd450FindILsb = 73, - GLSLstd450FindSMsb = 74, - GLSLstd450FindUMsb = 75, - - GLSLstd450InterpolateAtCentroid = 76, - GLSLstd450InterpolateAtSample = 77, - GLSLstd450InterpolateAtOffset = 78, - - GLSLstd450NMin = 79, - GLSLstd450NMax = 80, - GLSLstd450NClamp = 81, - - GLSLstd450Count -}; - -#endif // #ifndef GLSLstd450_H diff --git a/third_party/glslang-spirv/GlslangToSpv.cpp b/third_party/glslang-spirv/GlslangToSpv.cpp deleted file mode 100644 index 6e9fb38bb..000000000 --- a/third_party/glslang-spirv/GlslangToSpv.cpp +++ /dev/null @@ -1,6146 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// 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 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Visit the nodes in the glslang intermediate tree representation to -// translate them to SPIR-V. -// - -#include "spirv.hpp" -#include "GlslangToSpv.h" -#include "SpvBuilder.h" -namespace spv { - #include "GLSL.std.450.h" - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" -#ifdef AMD_EXTENSIONS - #include "GLSL.ext.AMD.h" -#endif -#ifdef NV_EXTENSIONS - #include "GLSL.ext.NV.h" -#endif -} - -#ifdef ENABLE_OPT - #include "spirv-tools/optimizer.hpp" - #include "message.h" - #include "SPVRemapper.h" -#endif - -#ifdef ENABLE_OPT -using namespace spvtools; -#endif - -// Glslang includes -#include "../glslang/MachineIndependent/localintermediate.h" -#include "../glslang/MachineIndependent/SymbolTable.h" -#include "../glslang/Include/Common.h" -#include "../glslang/Include/revision.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace { - -namespace { -class SpecConstantOpModeGuard { -public: - SpecConstantOpModeGuard(spv::Builder* builder) - : builder_(builder) { - previous_flag_ = builder->isInSpecConstCodeGenMode(); - } - ~SpecConstantOpModeGuard() { - previous_flag_ ? builder_->setToSpecConstCodeGenMode() - : builder_->setToNormalCodeGenMode(); - } - void turnOnSpecConstantOpMode() { - builder_->setToSpecConstCodeGenMode(); - } - -private: - spv::Builder* builder_; - bool previous_flag_; -}; -} - -// -// The main holder of information for translating glslang to SPIR-V. -// -// Derives from the AST walking base class. -// -class TGlslangToSpvTraverser : public glslang::TIntermTraverser { -public: - TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate*, spv::SpvBuildLogger* logger, - glslang::SpvOptions& options); - virtual ~TGlslangToSpvTraverser() { } - - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*); - bool visitBinary(glslang::TVisit, glslang::TIntermBinary*); - void visitConstantUnion(glslang::TIntermConstantUnion*); - bool visitSelection(glslang::TVisit, glslang::TIntermSelection*); - bool visitSwitch(glslang::TVisit, glslang::TIntermSwitch*); - void visitSymbol(glslang::TIntermSymbol* symbol); - bool visitUnary(glslang::TVisit, glslang::TIntermUnary*); - bool visitLoop(glslang::TVisit, glslang::TIntermLoop*); - bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*); - - void finishSpv(); - void dumpSpv(std::vector& out); - -protected: - spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier); - spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration); - spv::ImageFormat TranslateImageFormat(const glslang::TType& type); - spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const; - spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const; - spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, unsigned int& dependencyLength) const; - spv::StorageClass TranslateStorageClass(const glslang::TType&); - spv::Id createSpvVariable(const glslang::TIntermSymbol*); - spv::Id getSampledType(const glslang::TSampler&); - spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&); - spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult); - void convertSwizzle(const glslang::TIntermAggregate&, std::vector& swizzle); - spv::Id convertGlslangToSpvType(const glslang::TType& type); - spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&); - bool filterMember(const glslang::TType& member); - spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, - glslang::TLayoutPacking, const glslang::TQualifier&); - void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, - const glslang::TQualifier&, spv::Id); - spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim); - spv::Id accessChainLoad(const glslang::TType& type); - void accessChainStore(const glslang::TType& type, spv::Id rvalue); - void multiTypeStore(const glslang::TType&, spv::Id rValue); - glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; - int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember); - - bool isShaderEntryPoint(const glslang::TIntermAggregate* node); - bool writableParam(glslang::TStorageQualifier); - bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam); - void makeFunctions(const glslang::TIntermSequence&); - void makeGlobalInitializers(const glslang::TIntermSequence&); - void visitFunctions(const glslang::TIntermSequence&); - void handleFunctionEntry(const glslang::TIntermAggregate* node); - void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments); - void translateArguments(glslang::TIntermUnary& node, std::vector& arguments); - spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); - spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); - - spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true); - spv::Id createBinaryMatrixOperation(spv::Op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right); - spv::Id createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy); - spv::Id createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand,glslang::TBasicType typeProxy); - spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id destTypeId, spv::Id operand, glslang::TBasicType typeProxy); - spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); - spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector& operands); - spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); - spv::Id getSymbolId(const glslang::TIntermSymbol* node); - void addDecoration(spv::Id id, spv::Decoration dec); - void addDecoration(spv::Id id, spv::Decoration dec, unsigned value); - void addMemberDecoration(spv::Id id, int member, spv::Decoration dec); - void addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value); - spv::Id createSpvConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, int& nextConst, bool specConstant); - bool isTrivialLeaf(const glslang::TIntermTyped* node); - bool isTrivial(const glslang::TIntermTyped* node); - spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); -#ifdef AMD_EXTENSIONS - spv::Id getExtBuiltins(const char* name); -#endif - - glslang::SpvOptions& options; - spv::Function* shaderEntry; - spv::Function* currentFunction; - spv::Instruction* entryPoint; - int sequenceDepth; - - spv::SpvBuildLogger* logger; - - // There is a 1:1 mapping between a spv builder and a module; this is thread safe - spv::Builder builder; - bool inEntryPoint; - bool entryPointTerminated; - bool linkageOnly; // true when visiting the set of objects in the AST present only for establishing interface, whether or not they were statically used - std::set iOSet; // all input/output variables from either static use or declaration of interface - const glslang::TIntermediate* glslangIntermediate; - spv::Id stdBuiltins; - std::unordered_map extBuiltinMap; - - std::unordered_map symbolValues; - std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, rather than a pointer - std::unordered_map functionMap; - std::unordered_map structMap[glslang::ElpCount][glslang::ElmCount]; - std::unordered_map > memberRemapper; // for mapping glslang block indices to spv indices (e.g., due to hidden members) - std::stack breakForLoop; // false means break for switch -}; - -// -// Helper functions for translating glslang representations to SPIR-V enumerants. -// - -// Translate glslang profile to SPIR-V source language. -spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile) -{ - switch (source) { - case glslang::EShSourceGlsl: - switch (profile) { - case ENoProfile: - case ECoreProfile: - case ECompatibilityProfile: - return spv::SourceLanguageGLSL; - case EEsProfile: - return spv::SourceLanguageESSL; - default: - return spv::SourceLanguageUnknown; - } - case glslang::EShSourceHlsl: - return spv::SourceLanguageHLSL; - default: - return spv::SourceLanguageUnknown; - } -} - -// Translate glslang language (stage) to SPIR-V execution model. -spv::ExecutionModel TranslateExecutionModel(EShLanguage stage) -{ - switch (stage) { - case EShLangVertex: return spv::ExecutionModelVertex; - case EShLangTessControl: return spv::ExecutionModelTessellationControl; - case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation; - case EShLangGeometry: return spv::ExecutionModelGeometry; - case EShLangFragment: return spv::ExecutionModelFragment; - case EShLangCompute: return spv::ExecutionModelGLCompute; - default: - assert(0); - return spv::ExecutionModelFragment; - } -} - -// Translate glslang sampler type to SPIR-V dimensionality. -spv::Dim TranslateDimensionality(const glslang::TSampler& sampler) -{ - switch (sampler.dim) { - case glslang::Esd1D: return spv::Dim1D; - case glslang::Esd2D: return spv::Dim2D; - case glslang::Esd3D: return spv::Dim3D; - case glslang::EsdCube: return spv::DimCube; - case glslang::EsdRect: return spv::DimRect; - case glslang::EsdBuffer: return spv::DimBuffer; - case glslang::EsdSubpass: return spv::DimSubpassData; - default: - assert(0); - return spv::Dim2D; - } -} - -// Translate glslang precision to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(glslang::TPrecisionQualifier glslangPrecision) -{ - switch (glslangPrecision) { - case glslang::EpqLow: return spv::DecorationRelaxedPrecision; - case glslang::EpqMedium: return spv::DecorationRelaxedPrecision; - default: - return spv::NoPrecision; - } -} - -// Translate glslang type to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type) -{ - return TranslatePrecisionDecoration(type.getQualifier().precision); -} - -// Translate glslang type to SPIR-V block decorations. -spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useStorageBuffer) -{ - if (type.getBasicType() == glslang::EbtBlock) { - switch (type.getQualifier().storage) { - case glslang::EvqUniform: return spv::DecorationBlock; - case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; - case glslang::EvqVaryingIn: return spv::DecorationBlock; - case glslang::EvqVaryingOut: return spv::DecorationBlock; - default: - assert(0); - break; - } - } - - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V memory decorations. -void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory) -{ - if (qualifier.coherent) - memory.push_back(spv::DecorationCoherent); - if (qualifier.volatil) - memory.push_back(spv::DecorationVolatile); - if (qualifier.restrict) - memory.push_back(spv::DecorationRestrict); - if (qualifier.readonly) - memory.push_back(spv::DecorationNonWritable); - if (qualifier.writeonly) - memory.push_back(spv::DecorationNonReadable); -} - -// Translate glslang type to SPIR-V layout decorations. -spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout) -{ - if (type.isMatrix()) { - switch (matrixLayout) { - case glslang::ElmRowMajor: - return spv::DecorationRowMajor; - case glslang::ElmColumnMajor: - return spv::DecorationColMajor; - default: - // opaque layouts don't need a majorness - return spv::DecorationMax; - } - } else { - switch (type.getBasicType()) { - default: - return spv::DecorationMax; - break; - case glslang::EbtBlock: - switch (type.getQualifier().storage) { - case glslang::EvqUniform: - case glslang::EvqBuffer: - switch (type.getQualifier().layoutPacking) { - case glslang::ElpShared: return spv::DecorationGLSLShared; - case glslang::ElpPacked: return spv::DecorationGLSLPacked; - default: - return spv::DecorationMax; - } - case glslang::EvqVaryingIn: - case glslang::EvqVaryingOut: - assert(type.getQualifier().layoutPacking == glslang::ElpNone); - return spv::DecorationMax; - default: - assert(0); - return spv::DecorationMax; - } - } - } -} - -// Translate glslang type to SPIR-V interpolation decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.smooth) - // Smooth decoration doesn't exist in SPIR-V 1.0 - return spv::DecorationMax; - else if (qualifier.nopersp) - return spv::DecorationNoPerspective; - else if (qualifier.flat) - return spv::DecorationFlat; -#ifdef AMD_EXTENSIONS - else if (qualifier.explicitInterp) { - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::DecorationExplicitInterpAMD; - } -#endif - else - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V auxiliary storage decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.patch) - return spv::DecorationPatch; - else if (qualifier.centroid) - return spv::DecorationCentroid; - else if (qualifier.sample) { - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::DecorationSample; - } else - return spv::DecorationMax; -} - -// If glslang type is invariant, return SPIR-V invariant decoration. -spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.invariant) - return spv::DecorationInvariant; - else - return spv::DecorationMax; -} - -// If glslang type is noContraction, return SPIR-V NoContraction decoration. -spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.noContraction) - return spv::DecorationNoContraction; - else - return spv::DecorationMax; -} - -// Translate a glslang built-in variable to a SPIR-V built in decoration. Also generate -// associated capabilities when required. For some built-in variables, a capability -// is generated only when using the variable in an executable instruction, but not when -// just declaring a struct member variable with it. This is true for PointSize, -// ClipDistance, and CullDistance. -spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, bool memberDeclaration) -{ - switch (builtIn) { - case glslang::EbvPointSize: - // Defer adding the capability until the built-in is actually used. - if (! memberDeclaration) { - switch (glslangIntermediate->getStage()) { - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometryPointSize); - break; - case EShLangTessControl: - case EShLangTessEvaluation: - builder.addCapability(spv::CapabilityTessellationPointSize); - break; - default: - break; - } - } - return spv::BuiltInPointSize; - - // These *Distance capabilities logically belong here, but if the member is declared and - // then never used, consumers of SPIR-V prefer the capability not be declared. - // They are now generated when used, rather than here when declared. - // Potentially, the specification should be more clear what the minimum - // use needed is to trigger the capability. - // - case glslang::EbvClipDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityClipDistance); - return spv::BuiltInClipDistance; - - case glslang::EbvCullDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityCullDistance); - return spv::BuiltInCullDistance; - - case glslang::EbvViewportIndex: - builder.addCapability(spv::CapabilityMultiViewport); - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } - return spv::BuiltInViewportIndex; - - case glslang::EbvSampleId: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSampleId; - - case glslang::EbvSamplePosition: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSamplePosition; - - case glslang::EbvSampleMask: - return spv::BuiltInSampleMask; - - case glslang::EbvLayer: - builder.addCapability(spv::CapabilityGeometry); - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - builder.addExtension(spv::E_SPV_EXT_shader_viewport_index_layer); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } - return spv::BuiltInLayer; - - case glslang::EbvPosition: return spv::BuiltInPosition; - case glslang::EbvVertexId: return spv::BuiltInVertexId; - case glslang::EbvInstanceId: return spv::BuiltInInstanceId; - case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex; - case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex; - - case glslang::EbvBaseVertex: - builder.addExtension(spv::E_SPV_KHR_shader_draw_parameters); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseVertex; - - case glslang::EbvBaseInstance: - builder.addExtension(spv::E_SPV_KHR_shader_draw_parameters); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseInstance; - - case glslang::EbvDrawId: - builder.addExtension(spv::E_SPV_KHR_shader_draw_parameters); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInDrawIndex; - - case glslang::EbvPrimitiveId: - if (glslangIntermediate->getStage() == EShLangFragment) - builder.addCapability(spv::CapabilityGeometry); - return spv::BuiltInPrimitiveId; - - case glslang::EbvFragStencilRef: - builder.addExtension(spv::E_SPV_EXT_shader_stencil_export); - builder.addCapability(spv::CapabilityStencilExportEXT); - return spv::BuiltInFragStencilRefEXT; - - case glslang::EbvInvocationId: return spv::BuiltInInvocationId; - case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner; - case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter; - case glslang::EbvTessCoord: return spv::BuiltInTessCoord; - case glslang::EbvPatchVertices: return spv::BuiltInPatchVertices; - case glslang::EbvFragCoord: return spv::BuiltInFragCoord; - case glslang::EbvPointCoord: return spv::BuiltInPointCoord; - case glslang::EbvFace: return spv::BuiltInFrontFacing; - case glslang::EbvFragDepth: return spv::BuiltInFragDepth; - case glslang::EbvHelperInvocation: return spv::BuiltInHelperInvocation; - case glslang::EbvNumWorkGroups: return spv::BuiltInNumWorkgroups; - case glslang::EbvWorkGroupSize: return spv::BuiltInWorkgroupSize; - case glslang::EbvWorkGroupId: return spv::BuiltInWorkgroupId; - case glslang::EbvLocalInvocationId: return spv::BuiltInLocalInvocationId; - case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex; - case glslang::EbvGlobalInvocationId: return spv::BuiltInGlobalInvocationId; - - case glslang::EbvSubGroupSize: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupSize; - - case glslang::EbvSubGroupInvocation: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLocalInvocationId; - - case glslang::EbvSubGroupEqMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupEqMaskKHR; - - case glslang::EbvSubGroupGeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGeMaskKHR; - - case glslang::EbvSubGroupGtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGtMaskKHR; - - case glslang::EbvSubGroupLeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLeMaskKHR; - - case glslang::EbvSubGroupLtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLtMaskKHR; - -#ifdef AMD_EXTENSIONS - case glslang::EbvBaryCoordNoPersp: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspAMD; - - case glslang::EbvBaryCoordNoPerspCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspCentroidAMD; - - case glslang::EbvBaryCoordNoPerspSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspSampleAMD; - - case glslang::EbvBaryCoordSmooth: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothAMD; - - case glslang::EbvBaryCoordSmoothCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothCentroidAMD; - - case glslang::EbvBaryCoordSmoothSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothSampleAMD; - - case glslang::EbvBaryCoordPullModel: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordPullModelAMD; -#endif - - case glslang::EbvDeviceIndex: - builder.addExtension(spv::E_SPV_KHR_device_group); - builder.addCapability(spv::CapabilityDeviceGroup); - return spv::BuiltInDeviceIndex; - - case glslang::EbvViewIndex: - builder.addExtension(spv::E_SPV_KHR_multiview); - builder.addCapability(spv::CapabilityMultiView); - return spv::BuiltInViewIndex; - -#ifdef NV_EXTENSIONS - case glslang::EbvViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_viewport_array2); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - } - return spv::BuiltInViewportMaskNV; - case glslang::EbvSecondaryPositionNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryPositionNV; - case glslang::EbvSecondaryViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryViewportMaskNV; - case glslang::EbvPositionPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInPositionPerViewNV; - case glslang::EbvViewportMaskPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInViewportMaskPerViewNV; - case glslang::EbvFragFullyCoveredNV: - builder.addExtension(spv::E_SPV_EXT_fragment_fully_covered); - builder.addCapability(spv::CapabilityFragmentFullyCoveredEXT); - return spv::BuiltInFullyCoveredEXT; -#endif - default: - return spv::BuiltInMax; - } -} - -// Translate glslang image layout format to SPIR-V image format. -spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type) -{ - assert(type.getBasicType() == glslang::EbtSampler); - - // Check for capabilities - switch (type.getQualifier().layoutFormat) { - case glslang::ElfRg32f: - case glslang::ElfRg16f: - case glslang::ElfR11fG11fB10f: - case glslang::ElfR16f: - case glslang::ElfRgba16: - case glslang::ElfRgb10A2: - case glslang::ElfRg16: - case glslang::ElfRg8: - case glslang::ElfR16: - case glslang::ElfR8: - case glslang::ElfRgba16Snorm: - case glslang::ElfRg16Snorm: - case glslang::ElfRg8Snorm: - case glslang::ElfR16Snorm: - case glslang::ElfR8Snorm: - - case glslang::ElfRg32i: - case glslang::ElfRg16i: - case glslang::ElfRg8i: - case glslang::ElfR16i: - case glslang::ElfR8i: - - case glslang::ElfRgb10a2ui: - case glslang::ElfRg32ui: - case glslang::ElfRg16ui: - case glslang::ElfRg8ui: - case glslang::ElfR16ui: - case glslang::ElfR8ui: - builder.addCapability(spv::CapabilityStorageImageExtendedFormats); - break; - - default: - break; - } - - // do the translation - switch (type.getQualifier().layoutFormat) { - case glslang::ElfNone: return spv::ImageFormatUnknown; - case glslang::ElfRgba32f: return spv::ImageFormatRgba32f; - case glslang::ElfRgba16f: return spv::ImageFormatRgba16f; - case glslang::ElfR32f: return spv::ImageFormatR32f; - case glslang::ElfRgba8: return spv::ImageFormatRgba8; - case glslang::ElfRgba8Snorm: return spv::ImageFormatRgba8Snorm; - case glslang::ElfRg32f: return spv::ImageFormatRg32f; - case glslang::ElfRg16f: return spv::ImageFormatRg16f; - case glslang::ElfR11fG11fB10f: return spv::ImageFormatR11fG11fB10f; - case glslang::ElfR16f: return spv::ImageFormatR16f; - case glslang::ElfRgba16: return spv::ImageFormatRgba16; - case glslang::ElfRgb10A2: return spv::ImageFormatRgb10A2; - case glslang::ElfRg16: return spv::ImageFormatRg16; - case glslang::ElfRg8: return spv::ImageFormatRg8; - case glslang::ElfR16: return spv::ImageFormatR16; - case glslang::ElfR8: return spv::ImageFormatR8; - case glslang::ElfRgba16Snorm: return spv::ImageFormatRgba16Snorm; - case glslang::ElfRg16Snorm: return spv::ImageFormatRg16Snorm; - case glslang::ElfRg8Snorm: return spv::ImageFormatRg8Snorm; - case glslang::ElfR16Snorm: return spv::ImageFormatR16Snorm; - case glslang::ElfR8Snorm: return spv::ImageFormatR8Snorm; - case glslang::ElfRgba32i: return spv::ImageFormatRgba32i; - case glslang::ElfRgba16i: return spv::ImageFormatRgba16i; - case glslang::ElfRgba8i: return spv::ImageFormatRgba8i; - case glslang::ElfR32i: return spv::ImageFormatR32i; - case glslang::ElfRg32i: return spv::ImageFormatRg32i; - case glslang::ElfRg16i: return spv::ImageFormatRg16i; - case glslang::ElfRg8i: return spv::ImageFormatRg8i; - case glslang::ElfR16i: return spv::ImageFormatR16i; - case glslang::ElfR8i: return spv::ImageFormatR8i; - case glslang::ElfRgba32ui: return spv::ImageFormatRgba32ui; - case glslang::ElfRgba16ui: return spv::ImageFormatRgba16ui; - case glslang::ElfRgba8ui: return spv::ImageFormatRgba8ui; - case glslang::ElfR32ui: return spv::ImageFormatR32ui; - case glslang::ElfRg32ui: return spv::ImageFormatRg32ui; - case glslang::ElfRg16ui: return spv::ImageFormatRg16ui; - case glslang::ElfRgb10a2ui: return spv::ImageFormatRgb10a2ui; - case glslang::ElfRg8ui: return spv::ImageFormatRg8ui; - case glslang::ElfR16ui: return spv::ImageFormatR16ui; - case glslang::ElfR8ui: return spv::ImageFormatR8ui; - default: return spv::ImageFormatMax; - } -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl(const glslang::TIntermSelection& selectionNode) const -{ - if (selectionNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (selectionNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) const -{ - if (switchNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (switchNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -// return a non-0 dependency if the dependency argument must be set -spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode, - unsigned int& dependencyLength) const -{ - spv::LoopControlMask control = spv::LoopControlMaskNone; - - if (loopNode.getDontUnroll()) - control = control | spv::LoopControlDontUnrollMask; - if (loopNode.getUnroll()) - control = control | spv::LoopControlUnrollMask; - if (loopNode.getLoopDependency() == glslang::TIntermLoop::dependencyInfinite) - control = control | spv::LoopControlDependencyInfiniteMask; - else if (loopNode.getLoopDependency() > 0) { - control = control | spv::LoopControlDependencyLengthMask; - dependencyLength = loopNode.getLoopDependency(); - } - - return control; -} - -// Translate glslang type to SPIR-V storage class. -spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type) -{ - if (type.getQualifier().isPipeInput()) - return spv::StorageClassInput; - if (type.getQualifier().isPipeOutput()) - return spv::StorageClassOutput; - - if (glslangIntermediate->getSource() != glslang::EShSourceHlsl || - type.getQualifier().storage == glslang::EvqUniform) { - if (type.getBasicType() == glslang::EbtAtomicUint) - return spv::StorageClassAtomicCounter; - if (type.containsOpaque()) - return spv::StorageClassUniformConstant; - } - - if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { - builder.addExtension(spv::E_SPV_KHR_storage_buffer_storage_class); - return spv::StorageClassStorageBuffer; - } - - if (type.getQualifier().isUniformOrBuffer()) { - if (type.getQualifier().layoutPushConstant) - return spv::StorageClassPushConstant; - if (type.getBasicType() == glslang::EbtBlock) - return spv::StorageClassUniform; - return spv::StorageClassUniformConstant; - } - - switch (type.getQualifier().storage) { - case glslang::EvqShared: return spv::StorageClassWorkgroup; - case glslang::EvqGlobal: return spv::StorageClassPrivate; - case glslang::EvqConstReadOnly: return spv::StorageClassFunction; - case glslang::EvqTemporary: return spv::StorageClassFunction; - default: - assert(0); - break; - } - - return spv::StorageClassFunction; -} - -// Return whether or not the given type is something that should be tied to a -// descriptor set. -bool IsDescriptorResource(const glslang::TType& type) -{ - // uniform and buffer blocks are included, unless it is a push_constant - if (type.getBasicType() == glslang::EbtBlock) - return type.getQualifier().isUniformOrBuffer() && ! type.getQualifier().layoutPushConstant; - - // non block... - // basically samplerXXX/subpass/sampler/texture are all included - // if they are the global-scope-class, not the function parameter - // (or local, if they ever exist) class. - if (type.getBasicType() == glslang::EbtSampler) - return type.getQualifier().isUniformOrBuffer(); - - // None of the above. - return false; -} - -void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent) -{ - if (child.layoutMatrix == glslang::ElmNone) - child.layoutMatrix = parent.layoutMatrix; - - if (parent.invariant) - child.invariant = true; - if (parent.nopersp) - child.nopersp = true; -#ifdef AMD_EXTENSIONS - if (parent.explicitInterp) - child.explicitInterp = true; -#endif - if (parent.flat) - child.flat = true; - if (parent.centroid) - child.centroid = true; - if (parent.patch) - child.patch = true; - if (parent.sample) - child.sample = true; - if (parent.coherent) - child.coherent = true; - if (parent.volatil) - child.volatil = true; - if (parent.restrict) - child.restrict = true; - if (parent.readonly) - child.readonly = true; - if (parent.writeonly) - child.writeonly = true; -} - -bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier) -{ - // This should list qualifiers that simultaneous satisfy: - // - struct members might inherit from a struct declaration - // (note that non-block structs don't explicitly inherit, - // only implicitly, meaning no decoration involved) - // - affect decorations on the struct members - // (note smooth does not, and expecting something like volatile - // to effect the whole object) - // - are not part of the offset/st430/etc or row/column-major layout - return qualifier.invariant || (qualifier.hasLocation() && type.getBasicType() == glslang::EbtBlock); -} - -// -// Implement the TGlslangToSpvTraverser class. -// - -TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate* glslangIntermediate, - spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) - : TIntermTraverser(true, false, true), - options(options), - shaderEntry(nullptr), currentFunction(nullptr), - sequenceDepth(0), logger(buildLogger), - builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), - inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), - glslangIntermediate(glslangIntermediate) -{ - spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); - - builder.clearAccessChain(); - builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), - glslangIntermediate->getVersion()); - - if (options.generateDebugInfo) { - builder.setEmitOpLines(); - builder.setSourceFile(glslangIntermediate->getSourceFile()); - - // Set the source shader's text. If for SPV version 1.0, include - // a preamble in comments stating the OpModuleProcessed instructions. - // Otherwise, emit those as actual instructions. - std::string text; - const std::vector& processes = glslangIntermediate->getProcesses(); - for (int p = 0; p < (int)processes.size(); ++p) { - if (glslangIntermediate->getSpv().spv < 0x00010100) { - text.append("// OpModuleProcessed "); - text.append(processes[p]); - text.append("\n"); - } else - builder.addModuleProcessed(processes[p]); - } - if (glslangIntermediate->getSpv().spv < 0x00010100 && (int)processes.size() > 0) - text.append("#line 1\n"); - text.append(glslangIntermediate->getSourceText()); - builder.setSourceText(text); - } - stdBuiltins = builder.import("GLSL.std.450"); - builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); - shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str()); - entryPoint = builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str()); - - // Add the source extensions - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it) - builder.addSourceExtension(it->c_str()); - - // Add the top-level modes for this shader. - - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb); - } - - unsigned int mode; - switch (glslangIntermediate->getStage()) { - case EShLangVertex: - builder.addCapability(spv::CapabilityShader); - break; - - case EShLangTessEvaluation: - case EShLangTessControl: - builder.addCapability(spv::CapabilityTessellation); - - glslang::TLayoutGeometry primitive; - - if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - primitive = glslangIntermediate->getOutputPrimitive(); - } else { - primitive = glslangIntermediate->getInputPrimitive(); - } - - switch (primitive) { - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgQuads: mode = spv::ExecutionModeQuads; break; - case glslang::ElgIsolines: mode = spv::ExecutionModeIsolines; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexSpacing()) { - case glslang::EvsEqual: mode = spv::ExecutionModeSpacingEqual; break; - case glslang::EvsFractionalEven: mode = spv::ExecutionModeSpacingFractionalEven; break; - case glslang::EvsFractionalOdd: mode = spv::ExecutionModeSpacingFractionalOdd; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexOrder()) { - case glslang::EvoCw: mode = spv::ExecutionModeVertexOrderCw; break; - case glslang::EvoCcw: mode = spv::ExecutionModeVertexOrderCcw; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - if (glslangIntermediate->getPointMode()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePointMode); - break; - - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometry); - switch (glslangIntermediate->getInputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeInputPoints; break; - case glslang::ElgLines: mode = spv::ExecutionModeInputLines; break; - case glslang::ElgLinesAdjacency: mode = spv::ExecutionModeInputLinesAdjacency; break; - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations()); - - switch (glslangIntermediate->getOutputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; - case glslang::ElgLineStrip: mode = spv::ExecutionModeOutputLineStrip; break; - case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - break; - - case EShLangFragment: - builder.addCapability(spv::CapabilityShader); - if (glslangIntermediate->getPixelCenterInteger()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger); - - if (glslangIntermediate->getOriginUpperLeft()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft); - else - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft); - - if (glslangIntermediate->getEarlyFragmentTests()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); - - if (glslangIntermediate->getPostDepthCoverage()) { - builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); - builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); - builder.addExtension(spv::E_SPV_KHR_post_depth_coverage); - } - - switch(glslangIntermediate->getDepth()) { - case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; - case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - if (glslangIntermediate->getDepth() != glslang::EldUnchanged && glslangIntermediate->isDepthReplacing()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); - break; - - case EShLangCompute: - builder.addCapability(spv::CapabilityShader); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); - break; - - default: - break; - } -} - -// Finish creating SPV, after the traversal is complete. -void TGlslangToSpvTraverser::finishSpv() -{ - if (! entryPointTerminated) { - builder.setBuildPoint(shaderEntry->getLastBlock()); - builder.leaveFunction(); - } - - // finish off the entry-point SPV instruction by adding the Input/Output - for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it) - entryPoint->addIdOperand(*it); - - builder.eliminateDeadDecorations(); -} - -// Write the SPV into 'out'. -void TGlslangToSpvTraverser::dumpSpv(std::vector& out) -{ - builder.dump(out); -} - -// -// Implement the traversal functions. -// -// Return true from interior nodes to have the external traversal -// continue on to children. Return false if children were -// already processed. -// - -// -// Symbols can turn into -// - uniform/input reads -// - output writes -// - complex lvalue base setups: foo.bar[3].... , where we see foo and start up an access chain -// - something simple that degenerates into the last bullet -// -void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) -{ - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (symbol->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - // getSymbolId() will set up all the IO decorations on the first call. - // Formal function parameters were mapped during makeFunctions(). - spv::Id id = getSymbolId(symbol); - - // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction - if (builder.isPointer(id)) { - spv::StorageClass sc = builder.getStorageClass(id); - if (sc == spv::StorageClassInput || sc == spv::StorageClassOutput) { - if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) - iOSet.insert(id); - } - } - - // Only process non-linkage-only nodes for generating actual static uses - if (! linkageOnly || symbol->getQualifier().isSpecConstant()) { - // Prepare to generate code for the access - - // L-value chains will be computed left to right. We're on the symbol now, - // which is the left-most part of the access chain, so now is "clear" time, - // followed by setting the base. - builder.clearAccessChain(); - - // For now, we consider all user variables as being in memory, so they are pointers, - // except for - // A) R-Value arguments to a function, which are an intermediate object. - // See comments in handleUserFunctionCall(). - // B) Specialization constants (normal constants don't even come in as a variable), - // These are also pure R-values. - glslang::TQualifier qualifier = symbol->getQualifier(); - if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end()) - builder.setAccessChainRValue(id); - else - builder.setAccessChainLValue(id); - } -} - -bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) -{ - builder.setLine(node->getLoc().line); - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - // First, handle special cases - switch (node->getOp()) { - case glslang::EOpAssign: - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - case glslang::EOpAndAssign: - case glslang::EOpInclusiveOrAssign: - case glslang::EOpExclusiveOrAssign: - case glslang::EOpLeftShiftAssign: - case glslang::EOpRightShiftAssign: - // A bin-op assign "a += b" means the same thing as "a = a + b" - // where a is evaluated before b. For a simple assignment, GLSL - // says to evaluate the left before the right. So, always, left - // node then right node. - { - // get the left l-value, save it away - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Builder::AccessChain lValue = builder.getAccessChain(); - - // evaluate the right - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id rValue = accessChainLoad(node->getRight()->getType()); - - if (node->getOp() != glslang::EOpAssign) { - // the left is also an r-value - builder.setAccessChain(lValue); - spv::Id leftRValue = accessChainLoad(node->getLeft()->getType()); - - // do the operation - rValue = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - convertGlslangToSpvType(node->getType()), leftRValue, rValue, - node->getType().getBasicType()); - - // these all need their counterparts in createBinaryOperation() - assert(rValue != spv::NoResult); - } - - // store the result - builder.setAccessChain(lValue); - multiTypeStore(node->getType(), rValue); - - // assignments are expressions having an rValue after they are evaluated... - builder.clearAccessChain(); - builder.setAccessChainRValue(rValue); - } - return false; - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - { - // Get the left part of the access chain. - node->getLeft()->traverse(this); - - // Add the next element in the chain - - const int glslangIndex = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (! node->getLeft()->getType().isArray() && - node->getLeft()->getType().isVector() && - node->getOp() == glslang::EOpIndexDirect) { - // This is essentially a hard-coded vector swizzle of size 1, - // so short circuit the access-chain stuff with a swizzle. - std::vector swizzle; - swizzle.push_back(glslangIndex); - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType())); - } else { - int spvIndex = glslangIndex; - if (node->getLeft()->getBasicType() == glslang::EbtBlock && - node->getOp() == glslang::EOpIndexDirectStruct) - { - // This may be, e.g., an anonymous block-member selection, which generally need - // index remapping due to hidden members in anonymous blocks. - std::vector& remapper = memberRemapper[node->getLeft()->getType().getStruct()]; - assert(remapper.size() > 0); - spvIndex = remapper[glslangIndex]; - } - - // normal case for indexing array or structure or block - builder.accessChainPush(builder.makeIntConstant(spvIndex)); - - // Add capabilities here for accessing PointSize and clip/cull distance. - // We have deferred generation of associated capabilities until now. - if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray()) - declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex); - } - } - return false; - case glslang::EOpIndexIndirect: - { - // Structure or array or vector indirection. - // Will use native SPIR-V access-chain for struct and array indirection; - // matrices are arrays of vectors, so will also work for a matrix. - // Will use the access chain's 'component' for variable index into a vector. - - // This adapter is building access chains left to right. - // Set up the access chain to the left. - node->getLeft()->traverse(this); - - // save it so that computing the right side doesn't trash it - spv::Builder::AccessChain partial = builder.getAccessChain(); - - // compute the next index in the chain - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id index = accessChainLoad(node->getRight()->getType()); - - // restore the saved access chain - builder.setAccessChain(partial); - - if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) - builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType())); - else - builder.accessChainPush(index); - } - return false; - case glslang::EOpVectorSwizzle: - { - node->getLeft()->traverse(this); - std::vector swizzle; - convertSwizzle(*node->getRight()->getAsAggregate(), swizzle); - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType())); - } - return false; - case glslang::EOpMatrixSwizzle: - logger->missingFunctionality("matrix swizzle"); - return true; - case glslang::EOpLogicalOr: - case glslang::EOpLogicalAnd: - { - - // These may require short circuiting, but can sometimes be done as straight - // binary operations. The right operand must be short circuited if it has - // side effects, and should probably be if it is complex. - if (isTrivial(node->getRight()->getAsTyped())) - break; // handle below as a normal binary operation - // otherwise, we need to do dynamic short circuiting on the right operand - spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), *node->getRight()->getAsTyped()); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } - return false; - default: - break; - } - - // Assume generic binary op... - - // get right operand - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Id left = accessChainLoad(node->getLeft()->getType()); - - // get left operand - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id right = accessChainLoad(node->getRight()->getType()); - - // get result - spv::Id result = createBinaryOperation(node->getOp(), TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - convertGlslangToSpvType(node->getType()), left, right, - node->getLeft()->getType().getBasicType()); - - builder.clearAccessChain(); - if (! result) { - logger->missingFunctionality("unknown glslang binary operation"); - return true; // pick up a child as the place-holder result - } else { - builder.setAccessChainRValue(result); - return false; - } -} - -bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) -{ - builder.setLine(node->getLoc().line); - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - - // try texturing first - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // Non-texturing. - - if (node->getOp() == glslang::EOpArrayLength) { - // Quite special; won't want to evaluate the operand. - - // Normal .length() would have been constant folded by the front-end. - // So, this has to be block.lastMember.length(). - // SPV wants "block" and member number as the operands, go get them. - assert(node->getOperand()->getType().isRuntimeSizedArray()); - glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft(); - block->traverse(this); - unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion()->getConstArray()[0].getUConst(); - spv::Id length = builder.createArrayLength(builder.accessChainGetLValue(), member); - - builder.clearAccessChain(); - builder.setAccessChainRValue(length); - - return false; - } - - // Start by evaluating the operand - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - spv::Id invertedType = spv::NoType; - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; - if (node->getOp() == glslang::EOpInterpolateAtCentroid) - invertedType = getInvertedSwizzleType(*node->getOperand()); - - builder.clearAccessChain(); - if (invertedType != spv::NoType) - node->getOperand()->getAsBinaryNode()->getLeft()->traverse(this); - else - node->getOperand()->traverse(this); - - spv::Id operand = spv::NoResult; - - if (node->getOp() == glslang::EOpAtomicCounterIncrement || - node->getOp() == glslang::EOpAtomicCounterDecrement || - node->getOp() == glslang::EOpAtomicCounter || - node->getOp() == glslang::EOpInterpolateAtCentroid) - operand = builder.accessChainGetLValue(); // Special case l-value operands - else - operand = accessChainLoad(node->getOperand()->getType()); - - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); - spv::Decoration noContraction = TranslateNoContractionDecoration(node->getType().getQualifier()); - - // it could be a conversion - if (! result) - result = createConversion(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType()); - - // if not, then possibly an operation - if (! result) - result = createUnaryOperation(node->getOp(), precision, noContraction, resultType(), operand, node->getOperand()->getBasicType()); - - if (result) { - if (invertedType) - result = createInvertedSwizzle(precision, *node->getOperand(), result); - - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // it must be a special case, check... - switch (node->getOp()) { - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - { - // we need the integer value "1" or the floating point "1.0" to add/subtract - spv::Id one = 0; - if (node->getBasicType() == glslang::EbtFloat) - one = builder.makeFloatConstant(1.0F); - else if (node->getBasicType() == glslang::EbtDouble) - one = builder.makeDoubleConstant(1.0); -#ifdef AMD_EXTENSIONS - else if (node->getBasicType() == glslang::EbtFloat16) - one = builder.makeFloat16Constant(1.0F); -#endif - else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64) - one = builder.makeInt64Constant(1); -#ifdef AMD_EXTENSIONS - else if (node->getBasicType() == glslang::EbtInt16 || node->getBasicType() == glslang::EbtUint16) - one = builder.makeInt16Constant(1); -#endif - else - one = builder.makeIntConstant(1); - glslang::TOperator op; - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPostIncrement) - op = glslang::EOpAdd; - else - op = glslang::EOpSub; - - spv::Id result = createBinaryOperation(op, precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - convertGlslangToSpvType(node->getType()), operand, one, - node->getType().getBasicType()); - assert(result != spv::NoResult); - - // The result of operation is always stored, but conditionally the - // consumed result. The consumed result is always an r-value. - builder.accessChainStore(result); - builder.clearAccessChain(); - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPreDecrement) - builder.setAccessChainRValue(result); - else - builder.setAccessChainRValue(operand); - } - - return false; - - case glslang::EOpEmitStreamVertex: - builder.createNoResultOp(spv::OpEmitStreamVertex, operand); - return false; - case glslang::EOpEndStreamPrimitive: - builder.createNoResultOp(spv::OpEndStreamPrimitive, operand); - return false; - - default: - logger->missingFunctionality("unknown glslang unary"); - return true; // pick up operand as placeholder result - } -} - -bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node) -{ - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - spv::Id invertedType = spv::NoType; // to use to override the natural type of the node - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? invertedType : convertGlslangToSpvType(node->getType()); }; - - // try texturing - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; -#ifdef AMD_EXTENSIONS - } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) { -#else - } else if (node->getOp() == glslang::EOpImageStore) { -#endif - // "imageStore" is a special case, which has no result - return false; - } - - glslang::TOperator binOp = glslang::EOpNull; - bool reduceComparison = true; - bool isMatrix = false; - bool noReturnValue = false; - bool atomic = false; - - assert(node->getOp()); - - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); - - switch (node->getOp()) { - case glslang::EOpSequence: - { - if (preVisit) - ++sequenceDepth; - else - --sequenceDepth; - - if (sequenceDepth == 1) { - // If this is the parent node of all the functions, we want to see them - // early, so all call points have actual SPIR-V functions to reference. - // In all cases, still let the traverser visit the children for us. - makeFunctions(node->getAsAggregate()->getSequence()); - - // Also, we want all globals initializers to go into the beginning of the entry point, before - // anything else gets there, so visit out of order, doing them all now. - makeGlobalInitializers(node->getAsAggregate()->getSequence()); - - // Initializers are done, don't want to visit again, but functions and link objects need to be processed, - // so do them manually. - visitFunctions(node->getAsAggregate()->getSequence()); - - return false; - } - - return true; - } - case glslang::EOpLinkerObjects: - { - if (visit == glslang::EvPreVisit) - linkageOnly = true; - else - linkageOnly = false; - - return true; - } - case glslang::EOpComma: - { - // processing from left to right naturally leaves the right-most - // lying around in the access chain - glslang::TIntermSequence& glslangOperands = node->getSequence(); - for (int i = 0; i < (int)glslangOperands.size(); ++i) - glslangOperands[i]->traverse(this); - - return false; - } - case glslang::EOpFunction: - if (visit == glslang::EvPreVisit) { - if (isShaderEntryPoint(node)) { - inEntryPoint = true; - builder.setBuildPoint(shaderEntry->getLastBlock()); - currentFunction = shaderEntry; - } else { - handleFunctionEntry(node); - } - } else { - if (inEntryPoint) - entryPointTerminated = true; - builder.leaveFunction(); - inEntryPoint = false; - } - - return true; - case glslang::EOpParameters: - // Parameters will have been consumed by EOpFunction processing, but not - // the body, so we still visited the function node's children, making this - // child redundant. - return false; - case glslang::EOpFunctionCall: - { - builder.setLine(node->getLoc().line); - if (node->isUserDefined()) - result = handleUserFunctionCall(node); - // assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done - if (result) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } else - logger->missingFunctionality("missing user function; linker needs to catch that"); - - return false; - } - case glslang::EOpConstructMat2x2: - case glslang::EOpConstructMat2x3: - case glslang::EOpConstructMat2x4: - case glslang::EOpConstructMat3x2: - case glslang::EOpConstructMat3x3: - case glslang::EOpConstructMat3x4: - case glslang::EOpConstructMat4x2: - case glslang::EOpConstructMat4x3: - case glslang::EOpConstructMat4x4: - case glslang::EOpConstructDMat2x2: - case glslang::EOpConstructDMat2x3: - case glslang::EOpConstructDMat2x4: - case glslang::EOpConstructDMat3x2: - case glslang::EOpConstructDMat3x3: - case glslang::EOpConstructDMat3x4: - case glslang::EOpConstructDMat4x2: - case glslang::EOpConstructDMat4x3: - case glslang::EOpConstructDMat4x4: - case glslang::EOpConstructIMat2x2: - case glslang::EOpConstructIMat2x3: - case glslang::EOpConstructIMat2x4: - case glslang::EOpConstructIMat3x2: - case glslang::EOpConstructIMat3x3: - case glslang::EOpConstructIMat3x4: - case glslang::EOpConstructIMat4x2: - case glslang::EOpConstructIMat4x3: - case glslang::EOpConstructIMat4x4: - case glslang::EOpConstructUMat2x2: - case glslang::EOpConstructUMat2x3: - case glslang::EOpConstructUMat2x4: - case glslang::EOpConstructUMat3x2: - case glslang::EOpConstructUMat3x3: - case glslang::EOpConstructUMat3x4: - case glslang::EOpConstructUMat4x2: - case glslang::EOpConstructUMat4x3: - case glslang::EOpConstructUMat4x4: - case glslang::EOpConstructBMat2x2: - case glslang::EOpConstructBMat2x3: - case glslang::EOpConstructBMat2x4: - case glslang::EOpConstructBMat3x2: - case glslang::EOpConstructBMat3x3: - case glslang::EOpConstructBMat3x4: - case glslang::EOpConstructBMat4x2: - case glslang::EOpConstructBMat4x3: - case glslang::EOpConstructBMat4x4: -#ifdef AMD_EXTENSIONS - case glslang::EOpConstructF16Mat2x2: - case glslang::EOpConstructF16Mat2x3: - case glslang::EOpConstructF16Mat2x4: - case glslang::EOpConstructF16Mat3x2: - case glslang::EOpConstructF16Mat3x3: - case glslang::EOpConstructF16Mat3x4: - case glslang::EOpConstructF16Mat4x2: - case glslang::EOpConstructF16Mat4x3: - case glslang::EOpConstructF16Mat4x4: -#endif - isMatrix = true; - // fall through - case glslang::EOpConstructFloat: - case glslang::EOpConstructVec2: - case glslang::EOpConstructVec3: - case glslang::EOpConstructVec4: - case glslang::EOpConstructDouble: - case glslang::EOpConstructDVec2: - case glslang::EOpConstructDVec3: - case glslang::EOpConstructDVec4: -#ifdef AMD_EXTENSIONS - case glslang::EOpConstructFloat16: - case glslang::EOpConstructF16Vec2: - case glslang::EOpConstructF16Vec3: - case glslang::EOpConstructF16Vec4: -#endif - case glslang::EOpConstructBool: - case glslang::EOpConstructBVec2: - case glslang::EOpConstructBVec3: - case glslang::EOpConstructBVec4: - case glslang::EOpConstructInt: - case glslang::EOpConstructIVec2: - case glslang::EOpConstructIVec3: - case glslang::EOpConstructIVec4: - case glslang::EOpConstructUint: - case glslang::EOpConstructUVec2: - case glslang::EOpConstructUVec3: - case glslang::EOpConstructUVec4: - case glslang::EOpConstructInt64: - case glslang::EOpConstructI64Vec2: - case glslang::EOpConstructI64Vec3: - case glslang::EOpConstructI64Vec4: - case glslang::EOpConstructUint64: - case glslang::EOpConstructU64Vec2: - case glslang::EOpConstructU64Vec3: - case glslang::EOpConstructU64Vec4: -#ifdef AMD_EXTENSIONS - case glslang::EOpConstructInt16: - case glslang::EOpConstructI16Vec2: - case glslang::EOpConstructI16Vec3: - case glslang::EOpConstructI16Vec4: - case glslang::EOpConstructUint16: - case glslang::EOpConstructU16Vec2: - case glslang::EOpConstructU16Vec3: - case glslang::EOpConstructU16Vec4: -#endif - case glslang::EOpConstructStruct: - case glslang::EOpConstructTextureSampler: - { - builder.setLine(node->getLoc().line); - std::vector arguments; - translateArguments(*node, arguments); - spv::Id constructed; - if (node->getOp() == glslang::EOpConstructTextureSampler) - constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments); - else if (node->getOp() == glslang::EOpConstructStruct || node->getType().isArray()) { - std::vector constituents; - for (int c = 0; c < (int)arguments.size(); ++c) - constituents.push_back(arguments[c]); - constructed = builder.createCompositeConstruct(resultType(), constituents); - } else if (isMatrix) - constructed = builder.createMatrixConstructor(precision, arguments, resultType()); - else - constructed = builder.createConstructor(precision, arguments, resultType()); - - builder.clearAccessChain(); - builder.setAccessChainRValue(constructed); - - return false; - } - - // These six are component-wise compares with component-wise results. - // Forward on to createBinaryOperation(), requesting a vector result. - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - { - // Map the operation to a binary - binOp = node->getOp(); - reduceComparison = false; - switch (node->getOp()) { - case glslang::EOpVectorEqual: binOp = glslang::EOpVectorEqual; break; - case glslang::EOpVectorNotEqual: binOp = glslang::EOpVectorNotEqual; break; - default: binOp = node->getOp(); break; - } - - break; - } - case glslang::EOpMul: - // component-wise matrix multiply - binOp = glslang::EOpMul; - break; - case glslang::EOpOuterProduct: - // two vectors multiplied to make a matrix - binOp = glslang::EOpOuterProduct; - break; - case glslang::EOpDot: - { - // for scalar dot product, use multiply - glslang::TIntermSequence& glslangOperands = node->getSequence(); - if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1) - binOp = glslang::EOpMul; - break; - } - case glslang::EOpMod: - // when an aggregate, this is the floating-point mod built-in function, - // which can be emitted by the one in createBinaryOperation() - binOp = glslang::EOpMod; - break; - case glslang::EOpEmitVertex: - case glslang::EOpEndPrimitive: - case glslang::EOpBarrier: - case glslang::EOpMemoryBarrier: - case glslang::EOpMemoryBarrierAtomicCounter: - case glslang::EOpMemoryBarrierBuffer: - case glslang::EOpMemoryBarrierImage: - case glslang::EOpMemoryBarrierShared: - case glslang::EOpGroupMemoryBarrier: - case glslang::EOpDeviceMemoryBarrier: - case glslang::EOpAllMemoryBarrierWithGroupSync: - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - case glslang::EOpWorkgroupMemoryBarrier: - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - noReturnValue = true; - // These all have 0 operands and will naturally finish up in the code below for 0 operands - break; - - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - atomic = true; - break; - - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - builder.addExtension("SPV_KHR_shader_atomic_counter_ops"); - builder.addCapability(spv::CapabilityAtomicStorageOps); - atomic = true; - break; - - default: - break; - } - - // - // See if it maps to a regular operation. - // - if (binOp != glslang::EOpNull) { - glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped(); - glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped(); - assert(left && right); - - builder.clearAccessChain(); - left->traverse(this); - spv::Id leftId = accessChainLoad(left->getType()); - - builder.clearAccessChain(); - right->traverse(this); - spv::Id rightId = accessChainLoad(right->getType()); - - builder.setLine(node->getLoc().line); - result = createBinaryOperation(binOp, precision, TranslateNoContractionDecoration(node->getType().getQualifier()), - resultType(), leftId, rightId, - left->getType().getBasicType(), reduceComparison); - - // code above should only make binOp that exists in createBinaryOperation - assert(result != spv::NoResult); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; - } - - // - // Create the list of operands. - // - glslang::TIntermSequence& glslangOperands = node->getSequence(); - std::vector operands; - for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) { - // special case l-value operands; there are just a few - bool lvalue = false; - switch (node->getOp()) { - case glslang::EOpFrexp: - case glslang::EOpModf: - if (arg == 1) - lvalue = true; - break; - case glslang::EOpInterpolateAtSample: - case glslang::EOpInterpolateAtOffset: -#ifdef AMD_EXTENSIONS - case glslang::EOpInterpolateAtVertex: -#endif - if (arg == 0) { - lvalue = true; - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - if (glslangOperands[0]->getAsOperator() && - glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - invertedType = convertGlslangToSpvType(glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); - } - break; - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - if (arg == 0) - lvalue = true; - break; - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - if (arg == 2) - lvalue = true; - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - if (arg >= 2) - lvalue = true; - break; - default: - break; - } - builder.clearAccessChain(); - if (invertedType != spv::NoType && arg == 0) - glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this); - else - glslangOperands[arg]->traverse(this); - if (lvalue) - operands.push_back(builder.accessChainGetLValue()); - else { - builder.setLine(node->getLoc().line); - operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); - } - } - - builder.setLine(node->getLoc().line); - if (atomic) { - // Handle all atomics - result = createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - } else { - // Pass through to generic operations. - switch (glslangOperands.size()) { - case 0: - result = createNoArgOperation(node->getOp(), precision, resultType()); - break; - case 1: - result = createUnaryOperation( - node->getOp(), precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - resultType(), operands.front(), - glslangOperands[0]->getAsTyped()->getBasicType()); - break; - default: - result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - break; - } - if (invertedType) - result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result); - } - - if (noReturnValue) - return false; - - if (! result) { - logger->missingFunctionality("unknown glslang aggregate"); - return true; // pick up a child as a placeholder operand - } else { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - return false; - } -} - -// This path handles both if-then-else and ?: -// The if-then-else has a node type of void, while -// ?: has either a void or a non-void node type -// -// Leaving the result, when not void: -// GLSL only has r-values as the result of a :?, but -// if we have an l-value, that can be more efficient if it will -// become the base of a complex r-value expression, because the -// next layer copies r-values into memory to use the access-chain mechanism -bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node) -{ - // See if it simple and safe to generate OpSelect instead of using control flow. - // Crucially, side effects must be avoided, and there are performance trade-offs. - // Return true if good idea (and safe) for OpSelect, false otherwise. - const auto selectPolicy = [&]() -> bool { - if ((!node->getType().isScalar() && !node->getType().isVector()) || - node->getBasicType() == glslang::EbtVoid) - return false; - - if (node->getTrueBlock() == nullptr || - node->getFalseBlock() == nullptr) - return false; - - assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() && - node->getType() == node->getFalseBlock()->getAsTyped()->getType()); - - // return true if a single operand to ? : is okay for OpSelect - const auto operandOkay = [](glslang::TIntermTyped* node) { - return node->getAsSymbolNode() || node->getType().getQualifier().isConstant(); - }; - - return operandOkay(node->getTrueBlock() ->getAsTyped()) && - operandOkay(node->getFalseBlock()->getAsTyped()); - }; - - // Emit OpSelect for this selection. - const auto handleAsOpSelect = [&]() { - node->getCondition()->traverse(this); - spv::Id condition = accessChainLoad(node->getCondition()->getType()); - node->getTrueBlock()->traverse(this); - spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - node->getFalseBlock()->traverse(this); - spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - - builder.setLine(node->getLoc().line); - - // smear condition to vector, if necessary (AST is always scalar) - if (builder.isVector(trueValue)) - condition = builder.smearScalar(spv::NoPrecision, condition, - builder.makeVectorType(builder.makeBoolType(), - builder.getNumComponents(trueValue))); - - spv::Id select = builder.createTriOp(spv::OpSelect, - convertGlslangToSpvType(node->getType()), condition, - trueValue, falseValue); - builder.clearAccessChain(); - builder.setAccessChainRValue(select); - }; - - // Try for OpSelect - - if (selectPolicy()) { - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - handleAsOpSelect(); - return false; - } - - // Instead, emit control flow... - // Don't handle results as temporaries, because there will be two names - // and better to leave SSA to later passes. - spv::Id result = (node->getBasicType() == glslang::EbtVoid) - ? spv::NoResult - : builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType())); - - // emit the condition before doing anything with selection - node->getCondition()->traverse(this); - - // Selection control: - const spv::SelectionControlMask control = TranslateSelectionControl(*node); - - // make an "if" based on the value created by the condition - spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), control, builder); - - // emit the "then" statement - if (node->getTrueBlock() != nullptr) { - node->getTrueBlock()->traverse(this); - if (result != spv::NoResult) - builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result); - } - - if (node->getFalseBlock() != nullptr) { - ifBuilder.makeBeginElse(); - // emit the "else" statement - node->getFalseBlock()->traverse(this); - if (result != spv::NoResult) - builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result); - } - - // finish off the control flow - ifBuilder.makeEndIf(); - - if (result != spv::NoResult) { - // GLSL only has r-values as the result of a :?, but - // if we have an l-value, that can be more efficient if it will - // become the base of a complex r-value expression, because the - // next layer copies r-values into memory to use the access-chain mechanism - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - } - - return false; -} - -bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::TIntermSwitch* node) -{ - // emit and get the condition before doing anything with switch - node->getCondition()->traverse(this); - spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType()); - - // Selection control: - const spv::SelectionControlMask control = TranslateSwitchControl(*node); - - // browse the children to sort out code segments - int defaultSegment = -1; - std::vector codeSegments; - glslang::TIntermSequence& sequence = node->getBody()->getSequence(); - std::vector caseValues; - std::vector valueIndexToSegment(sequence.size()); // note: probably not all are used, it is an overestimate - for (glslang::TIntermSequence::iterator c = sequence.begin(); c != sequence.end(); ++c) { - TIntermNode* child = *c; - if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpDefault) - defaultSegment = (int)codeSegments.size(); - else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) { - valueIndexToSegment[caseValues.size()] = (int)codeSegments.size(); - caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion()->getConstArray()[0].getIConst()); - } else - codeSegments.push_back(child); - } - - // handle the case where the last code segment is missing, due to no code - // statements between the last case and the end of the switch statement - if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) || - (int)codeSegments.size() == defaultSegment) - codeSegments.push_back(nullptr); - - // make the switch statement - std::vector segmentBlocks; // returned, as the blocks allocated in the call - builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, segmentBlocks); - - // emit all the code in the segments - breakForLoop.push(false); - for (unsigned int s = 0; s < codeSegments.size(); ++s) { - builder.nextSwitchSegment(segmentBlocks, s); - if (codeSegments[s]) - codeSegments[s]->traverse(this); - else - builder.addSwitchBreak(); - } - breakForLoop.pop(); - - builder.endSwitch(segmentBlocks); - - return false; -} - -void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node) -{ - int nextConst = 0; - spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false); - - builder.clearAccessChain(); - builder.setAccessChainRValue(constant); -} - -bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node) -{ - auto blocks = builder.makeNewLoop(); - builder.createBranch(&blocks.head); - - // Loop control: - unsigned int dependencyLength = glslang::TIntermLoop::dependencyInfinite; - const spv::LoopControlMask control = TranslateLoopControl(*node, dependencyLength); - - // Spec requires back edges to target header blocks, and every header block - // must dominate its merge block. Make a header block first to ensure these - // conditions are met. By definition, it will contain OpLoopMerge, followed - // by a block-ending branch. But we don't want to put any other body/test - // instructions in it, since the body/test may have arbitrary instructions, - // including merges of its own. - builder.setLine(node->getLoc().line); - builder.setBuildPoint(&blocks.head); - builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, dependencyLength); - if (node->testFirst() && node->getTest()) { - spv::Block& test = builder.makeNewBlock(); - builder.createBranch(&test); - - builder.setBuildPoint(&test); - node->getTest()->traverse(this); - spv::Id condition = accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.body, &blocks.merge); - - builder.setBuildPoint(&blocks.body); - breakForLoop.push(true); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(&blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - builder.createBranch(&blocks.head); - } else { - builder.setLine(node->getLoc().line); - builder.createBranch(&blocks.body); - - breakForLoop.push(true); - builder.setBuildPoint(&blocks.body); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(&blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - if (node->getTest()) { - node->getTest()->traverse(this); - spv::Id condition = - accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.head, &blocks.merge); - } else { - // TODO: unless there was a break/return/discard instruction - // somewhere in the body, this is an infinite loop, so we should - // issue a warning. - builder.createBranch(&blocks.head); - } - } - builder.setBuildPoint(&blocks.merge); - builder.closeLoop(); - return false; -} - -bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::TIntermBranch* node) -{ - if (node->getExpression()) - node->getExpression()->traverse(this); - - builder.setLine(node->getLoc().line); - - switch (node->getFlowOp()) { - case glslang::EOpKill: - builder.makeDiscard(); - break; - case glslang::EOpBreak: - if (breakForLoop.top()) - builder.createLoopExit(); - else - builder.addSwitchBreak(); - break; - case glslang::EOpContinue: - builder.createLoopContinue(); - break; - case glslang::EOpReturn: - if (node->getExpression()) { - const glslang::TType& glslangReturnType = node->getExpression()->getType(); - spv::Id returnId = accessChainLoad(glslangReturnType); - if (builder.getTypeId(returnId) != currentFunction->getReturnType()) { - builder.clearAccessChain(); - spv::Id copyId = builder.createVariable(spv::StorageClassFunction, currentFunction->getReturnType()); - builder.setAccessChainLValue(copyId); - multiTypeStore(glslangReturnType, returnId); - returnId = builder.createLoad(copyId); - } - builder.makeReturn(false, returnId); - } else - builder.makeReturn(false); - - builder.clearAccessChain(); - break; - - default: - assert(0); - break; - } - - return false; -} - -spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node) -{ - // First, steer off constants, which are not SPIR-V variables, but - // can still have a mapping to a SPIR-V Id. - // This includes specialization constants. - if (node->getQualifier().isConstant()) { - return createSpvConstant(*node); - } - - // Now, handle actual variables - spv::StorageClass storageClass = TranslateStorageClass(node->getType()); - spv::Id spvType = convertGlslangToSpvType(node->getType()); - -#ifdef AMD_EXTENSIONS - const bool contains16BitType = node->getType().containsBasicType(glslang::EbtFloat16) || - node->getType().containsBasicType(glslang::EbtInt16) || - node->getType().containsBasicType(glslang::EbtUint16); - if (contains16BitType) { - if (storageClass == spv::StorageClassInput || storageClass == spv::StorageClassOutput) { - builder.addExtension(spv::E_SPV_KHR_16bit_storage); - builder.addCapability(spv::CapabilityStorageInputOutput16); - } else if (storageClass == spv::StorageClassPushConstant) { - builder.addExtension(spv::E_SPV_KHR_16bit_storage); - builder.addCapability(spv::CapabilityStoragePushConstant16); - } else if (storageClass == spv::StorageClassUniform) { - builder.addExtension(spv::E_SPV_KHR_16bit_storage); - builder.addCapability(spv::CapabilityStorageUniform16); - if (node->getType().getQualifier().storage == glslang::EvqBuffer) - builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); - } - } -#endif - - const char* name = node->getName().c_str(); - if (glslang::IsAnonymous(name)) - name = ""; - - return builder.createVariable(storageClass, spvType, name); -} - -// Return type Id of the sampled type. -spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler) -{ - switch (sampler.type) { - case glslang::EbtFloat: return builder.makeFloatType(32); - case glslang::EbtInt: return builder.makeIntType(32); - case glslang::EbtUint: return builder.makeUintType(32); - default: - assert(0); - return builder.makeFloatType(32); - } -} - -// If node is a swizzle operation, return the type that should be used if -// the swizzle base is first consumed by another operation, before the swizzle -// is applied. -spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyped& node) -{ - if (node.getAsOperator() && - node.getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - return convertGlslangToSpvType(node.getAsBinaryNode()->getLeft()->getType()); - else - return spv::NoType; -} - -// When inverting a swizzle with a parent op, this function -// will apply the swizzle operation to a completed parent operation. -spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, spv::Id parentResult) -{ - std::vector swizzle; - convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle); - return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle); -} - -// Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V. -void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector& swizzle) -{ - const glslang::TIntermSequence& swizzleSequence = node.getSequence(); - for (int i = 0; i < (int)swizzleSequence.size(); ++i) - swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst()); -} - -// Convert from a glslang type to an SPV type, by calling into a -// recursive version of this function. This establishes the inherited -// layout state rooted from the top-level type. -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type) -{ - return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier()); -} - -// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangStructToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier) -{ - spv::Id spvType = spv::NoResult; - - switch (type.getBasicType()) { - case glslang::EbtVoid: - spvType = builder.makeVoidType(); - assert (! type.isArray()); - break; - case glslang::EbtFloat: - spvType = builder.makeFloatType(32); - break; - case glslang::EbtDouble: - spvType = builder.makeFloatType(64); - break; -#ifdef AMD_EXTENSIONS - case glslang::EbtFloat16: - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - spvType = builder.makeFloatType(16); - break; -#endif - case glslang::EbtBool: - // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is - // a 32-bit int where non-0 means true. - if (explicitLayout != glslang::ElpNone) - spvType = builder.makeUintType(32); - else - spvType = builder.makeBoolType(); - break; - case glslang::EbtInt: - spvType = builder.makeIntType(32); - break; - case glslang::EbtUint: - spvType = builder.makeUintType(32); - break; - case glslang::EbtInt64: - spvType = builder.makeIntType(64); - break; - case glslang::EbtUint64: - spvType = builder.makeUintType(64); - break; -#ifdef AMD_EXTENSIONS - case glslang::EbtInt16: - builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); - spvType = builder.makeIntType(16); - break; - case glslang::EbtUint16: - builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); - spvType = builder.makeUintType(16); - break; -#endif - case glslang::EbtAtomicUint: - builder.addCapability(spv::CapabilityAtomicStorage); - spvType = builder.makeUintType(32); - break; - case glslang::EbtSampler: - { - const glslang::TSampler& sampler = type.getSampler(); - if (sampler.sampler) { - // pure sampler - spvType = builder.makeSamplerType(); - } else { - // an image is present, make its type - spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms, - sampler.image ? 2 : 1, TranslateImageFormat(type)); - if (sampler.combined) { - // already has both image and sampler, make the combined type - spvType = builder.makeSampledImageType(spvType); - } - } - } - break; - case glslang::EbtStruct: - case glslang::EbtBlock: - { - // If we've seen this struct type, return it - const glslang::TTypeList* glslangMembers = type.getStruct(); - - // Try to share structs for different layouts, but not yet for other - // kinds of qualification (primarily not yet including interpolant qualification). - if (! HasNonLayoutQualifiers(type, qualifier)) - spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers]; - if (spvType != spv::NoResult) - break; - - // else, we haven't seen it... - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers].resize(glslangMembers->size()); - spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); - } - break; - default: - assert(0); - break; - } - - if (type.isMatrix()) - spvType = builder.makeMatrixType(spvType, type.getMatrixCols(), type.getMatrixRows()); - else { - // If this variable has a vector element count greater than 1, create a SPIR-V vector - if (type.getVectorSize() > 1) - spvType = builder.makeVectorType(spvType, type.getVectorSize()); - } - - if (type.isArray()) { - int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride - - // Do all but the outer dimension - if (type.getArraySizes()->getNumDims() > 1) { - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) { - // Use a dummy glslang type for querying internal strides of - // arrays of arrays, but using just a one-dimensional array. - glslang::TType simpleArrayType(type, 0); // deference type of the array - while (simpleArrayType.getArraySizes().getNumDims() > 1) - simpleArrayType.getArraySizes().dereference(); - - // Will compute the higher-order strides here, rather than making a whole - // pile of types and doing repetitive recursion on their contents. - stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix); - } - - // make the arrays - for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) { - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), dim), stride); - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - stride *= type.getArraySizes()->getDimSize(dim); - } - } else { - // single-dimensional array, and don't yet have stride - - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) - stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix); - } - - // Do the outer dimension, which might not be known for a runtime-sized array - if (type.isRuntimeSizedArray()) { - spvType = builder.makeRuntimeArray(spvType); - } else { - assert(type.getOuterArraySize() > 0); - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride); - } - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - } - - return spvType; -} - -// TODO: this functionality should exist at a higher level, in creating the AST -// -// Identify interface members that don't have their required extension turned on. -// -bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member) -{ - auto& extensions = glslangIntermediate->getRequestedExtensions(); - - if (member.getFieldName() == "gl_ViewportMask" && - extensions.find("GL_NV_viewport_array2") == extensions.end()) - return true; - if (member.getFieldName() == "gl_SecondaryViewportMaskNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - if (member.getFieldName() == "gl_SecondaryPositionNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - if (member.getFieldName() == "gl_PositionPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - if (member.getFieldName() == "gl_ViewportMaskPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - - return false; -}; - -// Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier) -{ - // Create a vector of struct types for SPIR-V to consume - std::vector spvMembers; - int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks - for (int i = 0; i < (int)glslangMembers->size(); i++) { - glslang::TType& glslangMember = *(*glslangMembers)[i].type; - if (glslangMember.hiddenMember()) { - ++memberDelta; - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangMembers][i] = -1; - } else { - if (type.getBasicType() == glslang::EbtBlock) { - memberRemapper[glslangMembers][i] = i - memberDelta; - if (filterMember(glslangMember)) - continue; - } - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // manually inherit location - if (! memberQualifier.hasLocation() && qualifier.hasLocation()) - memberQualifier.layoutLocation = qualifier.layoutLocation; - - // recurse - spvMembers.push_back(convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier)); - } - } - - // Make the SPIR-V type - spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str()); - if (! HasNonLayoutQualifiers(type, qualifier)) - structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType; - - // Decorate it - decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType); - - return spvType; -} - -void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier, - spv::Id spvType) -{ - // Name and decorate the non-hidden members - int offset = -1; - int locationOffset = 0; // for use within the members of this struct - for (int i = 0; i < (int)glslangMembers->size(); i++) { - glslang::TType& glslangMember = *(*glslangMembers)[i].type; - int member = i; - if (type.getBasicType() == glslang::EbtBlock) { - member = memberRemapper[glslangMembers][i]; - if (filterMember(glslangMember)) - continue; - } - - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // using -1 above to indicate a hidden member - if (member >= 0) { - builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str()); - addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix)); - addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember)); - // Add interpolation and auxiliary storage decorations only to top-level members of Input and Output storage classes - if (type.getQualifier().storage == glslang::EvqVaryingIn || - type.getQualifier().storage == glslang::EvqVaryingOut) { - if (type.getBasicType() == glslang::EbtBlock || - glslangIntermediate->getSource() == glslang::EShSourceHlsl) { - addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier)); - addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier)); - } - } - addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier)); - - if (type.getBasicType() == glslang::EbtBlock && - qualifier.storage == glslang::EvqBuffer) { - // Add memory decorations only to top-level members of shader storage block - std::vector memory; - TranslateMemoryDecoration(memberQualifier, memory); - for (unsigned int i = 0; i < memory.size(); ++i) - addMemberDecoration(spvType, member, memory[i]); - } - - // Location assignment was already completed correctly by the front end, - // just track whether a member needs to be decorated. - // Ignore member locations if the container is an array, as that's - // ill-specified and decisions have been made to not allow this. - if (! type.isArray() && memberQualifier.hasLocation()) - builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation); - - if (qualifier.hasLocation()) // track for upcoming inheritance - locationOffset += glslangIntermediate->computeTypeLocationSize(glslangMember); - - // component, XFB, others - if (glslangMember.getQualifier().hasComponent()) - builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangMember.getQualifier().layoutComponent); - if (glslangMember.getQualifier().hasXfbOffset()) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangMember.getQualifier().layoutXfbOffset); - else if (explicitLayout != glslang::ElpNone) { - // figure out what to do with offset, which is accumulating - int nextOffset; - updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix); - if (offset >= 0) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); - offset = nextOffset; - } - - if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone) - builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix)); - - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true); - if (builtIn != spv::BuiltInMax) - addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); - -#ifdef NV_EXTENSIONS - if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (glslangMember.getQualifier().layoutViewportRelative){ - addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){ - addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - if (glslangMember.getQualifier().layoutPassthrough) { - addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } -#endif - } - } - - // Decorate the structure - addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); - addDecoration(spvType, TranslateBlockDecoration(type, glslangIntermediate->usingStorageBuffer())); - if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { - builder.addCapability(spv::CapabilityGeometryStreams); - builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); - } -} - -// Turn the expression forming the array size into an id. -// This is not quite trivial, because of specialization constants. -// Sometimes, a raw constant is turned into an Id, and sometimes -// a specialization constant expression is. -spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arraySizes, int dim) -{ - // First, see if this is sized with a node, meaning a specialization constant: - glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim); - if (specNode != nullptr) { - builder.clearAccessChain(); - specNode->traverse(this); - return accessChainLoad(specNode->getAsTyped()->getType()); - } - - // Otherwise, need a compile-time (front end) size, get it: - int size = arraySizes.getDimSize(dim); - assert(size > 0); - return builder.makeUintConstant(size); -} - -// Wrap the builder's accessChainLoad to: -// - localize handling of RelaxedPrecision -// - use the SPIR-V inferred type instead of another conversion of the glslang type -// (avoids unnecessary work and possible type punning for structures) -// - do conversion of concrete to abstract type -spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) -{ - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), nominalTypeId); - - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) - loadedId = builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) - loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } - } - - return loadedId; -} - -// Wrap the builder's accessChainStore to: -// - do conversion of concrete to abstract type -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::Id rvalue) -{ - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = builder.makeUintConstant(1); - spv::Id zero = builder.makeUintConstant(0); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != boolType) - rvalue = builder.createBinOp(spv::OpINotEqual, boolType, rvalue, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = makeSmearedConstant(builder.makeUintConstant(1), vecSize); - spv::Id zero = makeSmearedConstant(builder.makeUintConstant(0), vecSize); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != bvecType) - rvalue = builder.createBinOp(spv::OpINotEqual, bvecType, rvalue, - makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } - } - - builder.accessChainStore(rvalue); -} - -// For storing when types match at the glslang level, but not might match at the -// SPIR-V level. -// -// This especially happens when a single glslang type expands to multiple -// SPIR-V types, like a struct that is used in a member-undecorated way as well -// as in a member-decorated way. -// -// NOTE: This function can handle any store request; if it's not special it -// simplifies to a simple OpStore. -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id rValue) -{ - // we only do the complex path here if it's an aggregate - if (! type.isStruct() && ! type.isArray()) { - accessChainStore(type, rValue); - return; - } - - // and, it has to be a case of type aliasing - spv::Id rType = builder.getTypeId(rValue); - spv::Id lValue = builder.accessChainGetLValue(); - spv::Id lType = builder.getContainedTypeId(builder.getTypeId(lValue)); - if (lType == rType) { - accessChainStore(type, rValue); - return; - } - - // Recursively (as needed) copy an aggregate type to a different aggregate type, - // where the two types were the same type in GLSL. This requires member - // by member copy, recursively. - - // If an array, copy element by element. - if (type.isArray()) { - glslang::TType glslangElementType(type, 0); - spv::Id elementRType = builder.getContainedTypeId(rType); - for (int index = 0; index < type.getOuterArraySize(); ++index) { - // get the source member - spv::Id elementRValue = builder.createCompositeExtract(rValue, elementRType, index); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(index)); - - // store the member - multiTypeStore(glslangElementType, elementRValue); - } - } else { - assert(type.isStruct()); - - // loop over structure members - const glslang::TTypeList& members = *type.getStruct(); - for (int m = 0; m < (int)members.size(); ++m) { - const glslang::TType& glslangMemberType = *members[m].type; - - // get the source member - spv::Id memberRType = builder.getContainedTypeId(rType, m); - spv::Id memberRValue = builder.createCompositeExtract(rValue, memberRType, m); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(m)); - - // store the member - multiTypeStore(glslangMemberType, memberRValue); - } - } -} - -// Decide whether or not this type should be -// decorated with offsets and strides, and if so -// whether std140 or std430 rules should be applied. -glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang::TType& type) const -{ - // has to be a block - if (type.getBasicType() != glslang::EbtBlock) - return glslang::ElpNone; - - // has to be a uniform or buffer block - if (type.getQualifier().storage != glslang::EvqUniform && - type.getQualifier().storage != glslang::EvqBuffer) - return glslang::ElpNone; - - // return the layout to use - switch (type.getQualifier().layoutPacking) { - case glslang::ElpStd140: - case glslang::ElpStd430: - return type.getQualifier().layoutPacking; - default: - return glslang::ElpNone; - } -} - -// Given an array type, returns the integer stride required for that array -int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - int size; - int stride; - glslangIntermediate->getBaseAlignment(arrayType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix -// when used as a member of an interface block -int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - glslang::TType elementType; - elementType.shallowCopy(matrixType); - elementType.clearArraySizes(); - - int size; - int stride; - glslangIntermediate->getBaseAlignment(elementType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a member type of a struct, realign the current offset for it, and compute -// the next (not yet aligned) offset for the next member, which will get aligned -// on the next call. -// 'currentOffset' should be passed in already initialized, ready to modify, and reflecting -// the migration of data from nextOffset -> currentOffset. It should be -1 on the first call. -// -1 means a non-forced member offset (no decoration needed). -void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, - glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - // this will get a positive value when deemed necessary - nextOffset = -1; - - // override anything in currentOffset with user-set offset - if (memberType.getQualifier().hasOffset()) - currentOffset = memberType.getQualifier().layoutOffset; - - // It could be that current linker usage in glslang updated all the layoutOffset, - // in which case the following code does not matter. But, that's not quite right - // once cross-compilation unit GLSL validation is done, as the original user - // settings are needed in layoutOffset, and then the following will come into play. - - if (explicitLayout == glslang::ElpNone) { - if (! memberType.getQualifier().hasOffset()) - currentOffset = -1; - - return; - } - - // Getting this far means we need explicit offsets - if (currentOffset < 0) - currentOffset = 0; - - // Now, currentOffset is valid (either 0, or from a previous nextOffset), - // but possibly not yet correctly aligned. - - int memberSize; - int dummyStride; - int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor); - - // Adjust alignment for HLSL rules - // TODO: make this consistent in early phases of code: - // adjusting this late means inconsistencies with earlier code, which for reflection is an issue - // Until reflection is brought in sync with these adjustments, don't apply to $Global, - // which is the most likely to rely on reflection, and least likely to rely implicit layouts - if (glslangIntermediate->usingHlslOFfsets() && - ! memberType.isArray() && memberType.isVector() && structType.getTypeName().compare("$Global") != 0) { - int dummySize; - int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize); - if (componentAlignment <= 4) - memberAlignment = componentAlignment; - } - - // Bump up to member alignment - glslang::RoundToPow2(currentOffset, memberAlignment); - - // Bump up to vec4 if there is a bad straddle - if (glslangIntermediate->improperStraddle(memberType, memberSize, currentOffset)) - glslang::RoundToPow2(currentOffset, 16); - - nextOffset = currentOffset + memberSize; -} - -void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember) -{ - const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn; - switch (glslangBuiltIn) - { - case glslang::EbvClipDistance: - case glslang::EbvCullDistance: - case glslang::EbvPointSize: -#ifdef NV_EXTENSIONS - case glslang::EbvViewportMaskNV: - case glslang::EbvSecondaryPositionNV: - case glslang::EbvSecondaryViewportMaskNV: - case glslang::EbvPositionPerViewNV: - case glslang::EbvViewportMaskPerViewNV: -#endif - // Generate the associated capability. Delegate to TranslateBuiltInDecoration. - // Alternately, we could just call this for any glslang built-in, since the - // capability already guards against duplicates. - TranslateBuiltInDecoration(glslangBuiltIn, false); - break; - default: - // Capabilities were already generated when the struct was declared. - break; - } -} - -bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate* node) -{ - return node->getName().compare(glslangIntermediate->getEntryPointMangledName().c_str()) == 0; -} - -// Does parameter need a place to keep writes, separate from the original? -// Assumes called after originalParam(), which filters out block/buffer/opaque-based -// qualifiers such that we should have only in/out/inout/constreadonly here. -bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier) -{ - assert(qualifier == glslang::EvqIn || - qualifier == glslang::EvqOut || - qualifier == glslang::EvqInOut || - qualifier == glslang::EvqConstReadOnly); - return qualifier != glslang::EvqConstReadOnly; -} - -// Is parameter pass-by-original? -bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, const glslang::TType& paramType, - bool implicitThisParam) -{ - if (implicitThisParam) // implicit this - return true; - if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return paramType.getBasicType() == glslang::EbtBlock; - return paramType.containsOpaque() || // sampler, etc. - (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO -} - -// Make all the functions, skeletally, without actually visiting their bodies. -void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) -{ - const auto getParamDecorations = [](std::vector& decorations, const glslang::TType& type) { - spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); - if (paramPrecision != spv::NoPrecision) - decorations.push_back(paramPrecision); - TranslateMemoryDecoration(type.getQualifier(), decorations); - }; - - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate(); - if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction || isShaderEntryPoint(glslFunction)) - continue; - - // We're on a user function. Set up the basic interface for the function now, - // so that it's available to call. Translating the body will happen later. - // - // Typically (except for a "const in" parameter), an address will be passed to the - // function. What it is an address of varies: - // - // - "in" parameters not marked as "const" can be written to without modifying the calling - // argument so that write needs to be to a copy, hence the address of a copy works. - // - // - "const in" parameters can just be the r-value, as no writes need occur. - // - // - "out" and "inout" arguments can't be done as pointers to the calling argument, because - // GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy. - - std::vector paramTypes; - std::vector> paramDecorations; // list of decorations per parameter - glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence(); - - bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == - glslangIntermediate->implicitThisName; - - paramDecorations.resize(parameters.size()); - for (int p = 0; p < (int)parameters.size(); ++p) { - const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); - spv::Id typeId = convertGlslangToSpvType(paramType); - if (originalParam(paramType.getQualifier().storage, paramType, implicitThis && p == 0)) - typeId = builder.makePointer(TranslateStorageClass(paramType), typeId); - else if (writableParam(paramType.getQualifier().storage)) - typeId = builder.makePointer(spv::StorageClassFunction, typeId); - else - rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId()); - getParamDecorations(paramDecorations[p], paramType); - paramTypes.push_back(typeId); - } - - spv::Block* functionBlock; - spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()), - convertGlslangToSpvType(glslFunction->getType()), - glslFunction->getName().c_str(), paramTypes, - paramDecorations, &functionBlock); - if (implicitThis) - function->setImplicitThis(); - - // Track function to emit/call later - functionMap[glslFunction->getName().c_str()] = function; - - // Set the parameter id's - for (int p = 0; p < (int)parameters.size(); ++p) { - symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p); - // give a name too - builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str()); - } - } -} - -// Process all the initializers, while skipping the functions and link objects -void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequence& initializers) -{ - builder.setBuildPoint(shaderEntry->getLastBlock()); - for (int i = 0; i < (int)initializers.size(); ++i) { - glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate(); - if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != glslang::EOpLinkerObjects) { - - // We're on a top-level node that's not a function. Treat as an initializer, whose - // code goes into the beginning of the entry point. - initializer->traverse(this); - } - } -} - -// Process all the functions, while skipping initializers. -void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions) -{ - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* node = glslFunctions[f]->getAsAggregate(); - if (node && (node->getOp() == glslang::EOpFunction || node->getOp() == glslang::EOpLinkerObjects)) - node->traverse(this); - } -} - -void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node) -{ - // SPIR-V functions should already be in the functionMap from the prepass - // that called makeFunctions(). - currentFunction = functionMap[node->getName().c_str()]; - spv::Block* functionBlock = currentFunction->getEntryBlock(); - builder.setBuildPoint(functionBlock); -} - -void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments) -{ - const glslang::TIntermSequence& glslangArguments = node.getSequence(); - - glslang::TSampler sampler = {}; - bool cubeCompare = false; - if (node.isTexture() || node.isImage()) { - sampler = glslangArguments[0]->getAsTyped()->getType().getSampler(); - cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; - } - - for (int i = 0; i < (int)glslangArguments.size(); ++i) { - builder.clearAccessChain(); - glslangArguments[i]->traverse(this); - - // Special case l-value operands - bool lvalue = false; - switch (node.getOp()) { - case glslang::EOpImageAtomicAdd: - case glslang::EOpImageAtomicMin: - case glslang::EOpImageAtomicMax: - case glslang::EOpImageAtomicAnd: - case glslang::EOpImageAtomicOr: - case glslang::EOpImageAtomicXor: - case glslang::EOpImageAtomicExchange: - case glslang::EOpImageAtomicCompSwap: - if (i == 0) - lvalue = true; - break; - case glslang::EOpSparseImageLoad: - if ((sampler.ms && i == 3) || (! sampler.ms && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTexture: - if ((cubeCompare && i == 3) || (! cubeCompare && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureClamp: - if ((cubeCompare && i == 4) || (! cubeCompare && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLod: - case glslang::EOpSparseTextureOffset: - if (i == 3) - lvalue = true; - break; - case glslang::EOpSparseTextureFetch: - if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureFetchOffset: - if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLodOffset: - case glslang::EOpSparseTextureGrad: - case glslang::EOpSparseTextureOffsetClamp: - if (i == 4) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffset: - case glslang::EOpSparseTextureGradClamp: - if (i == 5) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffsetClamp: - if (i == 6) - lvalue = true; - break; - case glslang::EOpSparseTextureGather: - if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherOffset: - case glslang::EOpSparseTextureGatherOffsets: - if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3)) - lvalue = true; - break; -#ifdef AMD_EXTENSIONS - case glslang::EOpSparseTextureGatherLod: - if (i == 3) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherLodOffset: - case glslang::EOpSparseTextureGatherLodOffsets: - if (i == 4) - lvalue = true; - break; - case glslang::EOpSparseImageLoadLod: - if (i == 3) - lvalue = true; - break; -#endif - default: - break; - } - - if (lvalue) - arguments.push_back(builder.accessChainGetLValue()); - else - arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType())); - } -} - -void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector& arguments) -{ - builder.clearAccessChain(); - node.getOperand()->traverse(this); - arguments.push_back(accessChainLoad(node.getOperand()->getType())); -} - -spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node) -{ - if (! node->isImage() && ! node->isTexture()) - return spv::NoResult; - - builder.setLine(node->getLoc().line); - - auto resultType = [&node,this]{ return convertGlslangToSpvType(node->getType()); }; - - // Process a GLSL texturing op (will be SPV image) - const glslang::TSampler sampler = node->getAsAggregate() ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler() - : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType().getSampler(); - std::vector arguments; - if (node->getAsAggregate()) - translateArguments(*node->getAsAggregate(), arguments); - else - translateArguments(*node->getAsUnaryNode(), arguments); - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); - - spv::Builder::TextureParameters params = { }; - params.sampler = arguments[0]; - - glslang::TCrackedTextureOp cracked; - node->crackTexture(sampler, cracked); - - const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint; - - // Check for queries - if (cracked.query) { - // OpImageQueryLod works on a sampled image, for other queries the image has to be extracted first - if (node->getOp() != glslang::EOpTextureQueryLod && builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - - switch (node->getOp()) { - case glslang::EOpImageQuerySize: - case glslang::EOpTextureQuerySize: - if (arguments.size() > 1) { - params.lod = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult); - } else - return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult); - case glslang::EOpImageQuerySamples: - case glslang::EOpTextureQuerySamples: - return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult); - case glslang::EOpTextureQueryLod: - params.coords = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQueryLod, params, isUnsignedResult); - case glslang::EOpTextureQueryLevels: - return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult); - case glslang::EOpSparseTexelsResident: - return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]); - default: - assert(0); - break; - } - } - - // Check for image functions other than queries - if (node->isImage()) { - std::vector operands; - auto opIt = arguments.begin(); - operands.push_back(*(opIt++)); - - // Handle subpass operations - // TODO: GLSL should change to have the "MS" only on the type rather than the - // built-in function. - if (cracked.subpass) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps)); - if (sampler.ms) { - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*(opIt++)); - } - spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands); - builder.setPrecision(result, precision); - return result; - } - - operands.push_back(*(opIt++)); -#ifdef AMD_EXTENSIONS - if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) { -#else - if (node->getOp() == glslang::EOpImageLoad) { -#endif - if (sampler.ms) { - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*opIt); -#ifdef AMD_EXTENSIONS - } else if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - operands.push_back(spv::ImageOperandsLodMask); - operands.push_back(*opIt); -#endif - } - if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands); - builder.setPrecision(result, precision); - return result; -#ifdef AMD_EXTENSIONS - } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) { -#else - } else if (node->getOp() == glslang::EOpImageStore) { -#endif - if (sampler.ms) { - operands.push_back(*(opIt + 1)); - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*opIt); -#ifdef AMD_EXTENSIONS - } else if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - operands.push_back(*(opIt + 1)); - operands.push_back(spv::ImageOperandsLodMask); - operands.push_back(*opIt); -#endif - } else - operands.push_back(*opIt); - builder.createNoResultOp(spv::OpImageWrite, operands); - if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat); - return spv::NoResult; -#ifdef AMD_EXTENSIONS - } else if (node->getOp() == glslang::EOpSparseImageLoad || node->getOp() == glslang::EOpSparseImageLoadLod) { -#else - } else if (node->getOp() == glslang::EOpSparseImageLoad) { -#endif - builder.addCapability(spv::CapabilitySparseResidency); - if (builder.getImageTypeFormat(builder.getImageType(operands.front())) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - if (sampler.ms) { - operands.push_back(spv::ImageOperandsSampleMask); - operands.push_back(*opIt++); -#ifdef AMD_EXTENSIONS - } else if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - operands.push_back(spv::ImageOperandsLodMask); - operands.push_back(*opIt++); -#endif - } - - // Create the return type that was a special structure - spv::Id texelOut = *opIt; - spv::Id typeId0 = resultType(); - spv::Id typeId1 = builder.getDerefTypeId(texelOut); - spv::Id resultTypeId = builder.makeStructResultType(typeId0, typeId1); - - spv::Id resultId = builder.createOp(spv::OpImageSparseRead, resultTypeId, operands); - - // Decode the return type - builder.createStore(builder.createCompositeExtract(resultId, typeId1, 1), texelOut); - return builder.createCompositeExtract(resultId, typeId0, 0); - } else { - // Process image atomic operations - - // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer, - // as the first source operand, is required by SPIR-V atomic operations. - operands.push_back(sampler.ms ? *(opIt++) : builder.makeUintConstant(0)); // For non-MS, the value should be 0 - - spv::Id resultTypeId = builder.makePointer(spv::StorageClassImage, resultType()); - spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands); - - std::vector operands; - operands.push_back(pointer); - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - return createAtomicOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - } - } - -#ifdef AMD_EXTENSIONS - // Check for fragment mask functions other than queries - if (cracked.fragMask) { - assert(sampler.ms); - - auto opIt = arguments.begin(); - std::vector operands; - - // Extract the image if necessary - if (builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - - operands.push_back(params.sampler); - ++opIt; - - if (sampler.isSubpass()) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps)); - } - - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - spv::Op fragMaskOp = spv::OpNop; - if (node->getOp() == glslang::EOpFragmentMaskFetch) - fragMaskOp = spv::OpFragmentMaskFetchAMD; - else if (node->getOp() == glslang::EOpFragmentFetch) - fragMaskOp = spv::OpFragmentFetchAMD; - - builder.addExtension(spv::E_SPV_AMD_shader_fragment_mask); - builder.addCapability(spv::CapabilityFragmentMaskAMD); - return builder.createOp(fragMaskOp, resultType(), operands); - } -#endif - - // Check for texture functions other than queries - bool sparse = node->isSparseTexture(); - bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; - - // check for bias argument - bool bias = false; -#ifdef AMD_EXTENSIONS - if (! cracked.lod && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { -#else - if (! cracked.lod && ! cracked.gather && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { -#endif - int nonBiasArgCount = 2; -#ifdef AMD_EXTENSIONS - if (cracked.gather) - ++nonBiasArgCount; // comp argument should be present when bias argument is present -#endif - if (cracked.offset) - ++nonBiasArgCount; -#ifdef AMD_EXTENSIONS - else if (cracked.offsets) - ++nonBiasArgCount; -#endif - if (cracked.grad) - nonBiasArgCount += 2; - if (cracked.lodClamp) - ++nonBiasArgCount; - if (sparse) - ++nonBiasArgCount; - - if ((int)arguments.size() > nonBiasArgCount) - bias = true; - } - - // See if the sampler param should really be just the SPV image part - if (cracked.fetch) { - // a fetch needs to have the image extracted first - if (builder.isSampledImage(params.sampler)) - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - } - -#ifdef AMD_EXTENSIONS - if (cracked.gather) { - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - if (bias || cracked.lod || - sourceExtensions.find(glslang::E_GL_AMD_texture_gather_bias_lod) != sourceExtensions.end()) { - builder.addExtension(spv::E_SPV_AMD_texture_gather_bias_lod); - builder.addCapability(spv::CapabilityImageGatherBiasLodAMD); - } - } -#endif - - // set the rest of the arguments - - params.coords = arguments[1]; - int extraArgs = 0; - bool noImplicitLod = false; - - // sort out where Dref is coming from - if (cubeCompare) { - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow && cracked.gather) { - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow) { - std::vector indexes; - int dRefComp; - if (cracked.proj) - dRefComp = 2; // "The resulting 3rd component of P in the shadow forms is used as Dref" - else - dRefComp = builder.getNumComponents(params.coords) - 1; - indexes.push_back(dRefComp); - params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); - } - - // lod - if (cracked.lod) { - params.lod = arguments[2 + extraArgs]; - ++extraArgs; - } else if (glslangIntermediate->getStage() != EShLangFragment) { - // we need to invent the default lod for an explicit lod instruction for a non-fragment stage - noImplicitLod = true; - } - - // multisample - if (sampler.ms) { - params.sample = arguments[2 + extraArgs]; // For MS, "sample" should be specified - ++extraArgs; - } - - // gradient - if (cracked.grad) { - params.gradX = arguments[2 + extraArgs]; - params.gradY = arguments[3 + extraArgs]; - extraArgs += 2; - } - - // offset and offsets - if (cracked.offset) { - params.offset = arguments[2 + extraArgs]; - ++extraArgs; - } else if (cracked.offsets) { - params.offsets = arguments[2 + extraArgs]; - ++extraArgs; - } - - // lod clamp - if (cracked.lodClamp) { - params.lodClamp = arguments[2 + extraArgs]; - ++extraArgs; - } - - // sparse - if (sparse) { - params.texelOut = arguments[2 + extraArgs]; - ++extraArgs; - } - - // gather component - if (cracked.gather && ! sampler.shadow) { - // default component is 0, if missing, otherwise an argument - if (2 + extraArgs < (int)arguments.size()) { - params.component = arguments[2 + extraArgs]; - ++extraArgs; - } else - params.component = builder.makeIntConstant(0); - } - - // bias - if (bias) { - params.bias = arguments[2 + extraArgs]; - ++extraArgs; - } - - // projective component (might not to move) - // GLSL: "The texture coordinates consumed from P, not including the last component of P, - // are divided by the last component of P." - // SPIR-V: "... (u [, v] [, w], q)... It may be a vector larger than needed, but all - // unused components will appear after all used components." - if (cracked.proj) { - int projSourceComp = builder.getNumComponents(params.coords) - 1; - int projTargetComp; - switch (sampler.dim) { - case glslang::Esd1D: projTargetComp = 1; break; - case glslang::Esd2D: projTargetComp = 2; break; - case glslang::EsdRect: projTargetComp = 2; break; - default: projTargetComp = projSourceComp; break; - } - // copy the projective coordinate if we have to - if (projTargetComp != projSourceComp) { - spv::Id projComp = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), - projSourceComp); - params.coords = builder.createCompositeInsert(projComp, params.coords, - builder.getTypeId(params.coords), projTargetComp); - } - } - - return builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params); -} - -spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node) -{ - // Grab the function's pointer from the previously created function - spv::Function* function = functionMap[node->getName().c_str()]; - if (! function) - return 0; - - const glslang::TIntermSequence& glslangArgs = node->getSequence(); - const glslang::TQualifierList& qualifiers = node->getQualifierList(); - - // See comments in makeFunctions() for details about the semantics for parameter passing. - // - // These imply we need a four step process: - // 1. Evaluate the arguments - // 2. Allocate and make copies of in, out, and inout arguments - // 3. Make the call - // 4. Copy back the results - - // 1. Evaluate the arguments - std::vector lValues; - std::vector rValues; - std::vector argTypes; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType(); - // build l-value - builder.clearAccessChain(); - glslangArgs[a]->traverse(this); - argTypes.push_back(¶mType); - // keep outputs and pass-by-originals as l-values, evaluate others as r-values - if (originalParam(qualifiers[a], paramType, function->hasImplicitThis() && a == 0) || - writableParam(qualifiers[a])) { - // save l-value - lValues.push_back(builder.getAccessChain()); - } else { - // process r-value - rValues.push_back(accessChainLoad(*argTypes.back())); - } - } - - // 2. Allocate space for anything needing a copy, and if it's "in" or "inout" - // copy the original into that space. - // - // Also, build up the list of actual arguments to pass in for the call - int lValueCount = 0; - int rValueCount = 0; - std::vector spvArgs; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType(); - spv::Id arg; - if (originalParam(qualifiers[a], paramType, function->hasImplicitThis() && a == 0)) { - builder.setAccessChain(lValues[lValueCount]); - arg = builder.accessChainGetLValue(); - ++lValueCount; - } else if (writableParam(qualifiers[a])) { - // need space to hold the copy - arg = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(paramType), "param"); - if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) { - // need to copy the input into output space - builder.setAccessChain(lValues[lValueCount]); - spv::Id copy = accessChainLoad(*argTypes[a]); - builder.clearAccessChain(); - builder.setAccessChainLValue(arg); - multiTypeStore(paramType, copy); - } - ++lValueCount; - } else { - arg = rValues[rValueCount]; - ++rValueCount; - } - spvArgs.push_back(arg); - } - - // 3. Make the call. - spv::Id result = builder.createFunctionCall(function, spvArgs); - builder.setPrecision(result, TranslatePrecisionDecoration(node->getType())); - - // 4. Copy back out an "out" arguments. - lValueCount = 0; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType(); - if (originalParam(qualifiers[a], paramType, function->hasImplicitThis() && a == 0)) - ++lValueCount; - else if (writableParam(qualifiers[a])) { - if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) { - spv::Id copy = builder.createLoad(spvArgs[a]); - builder.setAccessChain(lValues[lValueCount]); - multiTypeStore(paramType, copy); - } - ++lValueCount; - } - } - - return result; -} - -// Translate AST operation to SPV operation, already having SPV-based operands/types. -spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv::Decoration precision, - spv::Decoration noContraction, - spv::Id typeId, spv::Id left, spv::Id right, - glslang::TBasicType typeProxy, bool reduceComparison) -{ -#ifdef AMD_EXTENSIONS - bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64 || typeProxy == glslang::EbtUint16; - bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16; -#else - bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64; - bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble; -#endif - bool isBool = typeProxy == glslang::EbtBool; - - spv::Op binOp = spv::OpNop; - bool needMatchingVectors = true; // for non-matrix ops, would a scalar need to smear to match a vector? - bool comparison = false; - - switch (op) { - case glslang::EOpAdd: - case glslang::EOpAddAssign: - if (isFloat) - binOp = spv::OpFAdd; - else - binOp = spv::OpIAdd; - break; - case glslang::EOpSub: - case glslang::EOpSubAssign: - if (isFloat) - binOp = spv::OpFSub; - else - binOp = spv::OpISub; - break; - case glslang::EOpMul: - case glslang::EOpMulAssign: - if (isFloat) - binOp = spv::OpFMul; - else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesScalar: - case glslang::EOpVectorTimesScalarAssign: - if (isFloat && (builder.isVector(left) || builder.isVector(right))) { - if (builder.isVector(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - needMatchingVectors = false; - binOp = spv::OpVectorTimesScalar; - } else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesMatrix: - case glslang::EOpVectorTimesMatrixAssign: - binOp = spv::OpVectorTimesMatrix; - break; - case glslang::EOpMatrixTimesVector: - binOp = spv::OpMatrixTimesVector; - break; - case glslang::EOpMatrixTimesScalar: - case glslang::EOpMatrixTimesScalarAssign: - binOp = spv::OpMatrixTimesScalar; - break; - case glslang::EOpMatrixTimesMatrix: - case glslang::EOpMatrixTimesMatrixAssign: - binOp = spv::OpMatrixTimesMatrix; - break; - case glslang::EOpOuterProduct: - binOp = spv::OpOuterProduct; - needMatchingVectors = false; - break; - - case glslang::EOpDiv: - case glslang::EOpDivAssign: - if (isFloat) - binOp = spv::OpFDiv; - else if (isUnsigned) - binOp = spv::OpUDiv; - else - binOp = spv::OpSDiv; - break; - case glslang::EOpMod: - case glslang::EOpModAssign: - if (isFloat) - binOp = spv::OpFMod; - else if (isUnsigned) - binOp = spv::OpUMod; - else - binOp = spv::OpSMod; - break; - case glslang::EOpRightShift: - case glslang::EOpRightShiftAssign: - if (isUnsigned) - binOp = spv::OpShiftRightLogical; - else - binOp = spv::OpShiftRightArithmetic; - break; - case glslang::EOpLeftShift: - case glslang::EOpLeftShiftAssign: - binOp = spv::OpShiftLeftLogical; - break; - case glslang::EOpAnd: - case glslang::EOpAndAssign: - binOp = spv::OpBitwiseAnd; - break; - case glslang::EOpLogicalAnd: - needMatchingVectors = false; - binOp = spv::OpLogicalAnd; - break; - case glslang::EOpInclusiveOr: - case glslang::EOpInclusiveOrAssign: - binOp = spv::OpBitwiseOr; - break; - case glslang::EOpLogicalOr: - needMatchingVectors = false; - binOp = spv::OpLogicalOr; - break; - case glslang::EOpExclusiveOr: - case glslang::EOpExclusiveOrAssign: - binOp = spv::OpBitwiseXor; - break; - case glslang::EOpLogicalXor: - needMatchingVectors = false; - binOp = spv::OpLogicalNotEqual; - break; - - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - comparison = true; - break; - default: - break; - } - - // handle mapped binary operations (should be non-comparison) - if (binOp != spv::OpNop) { - assert(comparison == false); - if (builder.isMatrix(left) || builder.isMatrix(right)) - return createBinaryMatrixOperation(binOp, precision, noContraction, typeId, left, right); - - // No matrix involved; make both operands be the same number of components, if needed - if (needMatchingVectors) - builder.promoteScalar(precision, left, right); - - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - addDecoration(result, noContraction); - return builder.setPrecision(result, precision); - } - - if (! comparison) - return 0; - - // Handle comparison instructions - - if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual) - && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) - return builder.createCompositeCompare(precision, left, right, op == glslang::EOpEqual); - - switch (op) { - case glslang::EOpLessThan: - if (isFloat) - binOp = spv::OpFOrdLessThan; - else if (isUnsigned) - binOp = spv::OpULessThan; - else - binOp = spv::OpSLessThan; - break; - case glslang::EOpGreaterThan: - if (isFloat) - binOp = spv::OpFOrdGreaterThan; - else if (isUnsigned) - binOp = spv::OpUGreaterThan; - else - binOp = spv::OpSGreaterThan; - break; - case glslang::EOpLessThanEqual: - if (isFloat) - binOp = spv::OpFOrdLessThanEqual; - else if (isUnsigned) - binOp = spv::OpULessThanEqual; - else - binOp = spv::OpSLessThanEqual; - break; - case glslang::EOpGreaterThanEqual: - if (isFloat) - binOp = spv::OpFOrdGreaterThanEqual; - else if (isUnsigned) - binOp = spv::OpUGreaterThanEqual; - else - binOp = spv::OpSGreaterThanEqual; - break; - case glslang::EOpEqual: - case glslang::EOpVectorEqual: - if (isFloat) - binOp = spv::OpFOrdEqual; - else if (isBool) - binOp = spv::OpLogicalEqual; - else - binOp = spv::OpIEqual; - break; - case glslang::EOpNotEqual: - case glslang::EOpVectorNotEqual: - if (isFloat) - binOp = spv::OpFOrdNotEqual; - else if (isBool) - binOp = spv::OpLogicalNotEqual; - else - binOp = spv::OpINotEqual; - break; - default: - break; - } - - if (binOp != spv::OpNop) { - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - addDecoration(result, noContraction); - return builder.setPrecision(result, precision); - } - - return 0; -} - -// -// Translate AST matrix operation to SPV operation, already having SPV-based operands/types. -// These can be any of: -// -// matrix * scalar -// scalar * matrix -// matrix * matrix linear algebraic -// matrix * vector -// vector * matrix -// matrix * matrix componentwise -// matrix op matrix op in {+, -, /} -// matrix op scalar op in {+, -, /} -// scalar op matrix op in {+, -, /} -// -spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id left, spv::Id right) -{ - bool firstClass = true; - - // First, handle first-class matrix operations (* and matrix/scalar) - switch (op) { - case spv::OpFDiv: - if (builder.isMatrix(left) && builder.isScalar(right)) { - // turn matrix / scalar into a multiply... - right = builder.createBinOp(spv::OpFDiv, builder.getTypeId(right), builder.makeFloatConstant(1.0F), right); - op = spv::OpMatrixTimesScalar; - } else - firstClass = false; - break; - case spv::OpMatrixTimesScalar: - if (builder.isMatrix(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - break; - case spv::OpVectorTimesMatrix: - assert(builder.isVector(left)); - assert(builder.isMatrix(right)); - break; - case spv::OpMatrixTimesVector: - assert(builder.isMatrix(left)); - assert(builder.isVector(right)); - break; - case spv::OpMatrixTimesMatrix: - assert(builder.isMatrix(left)); - assert(builder.isMatrix(right)); - break; - default: - firstClass = false; - break; - } - - if (firstClass) { - spv::Id result = builder.createBinOp(op, typeId, left, right); - addDecoration(result, noContraction); - return builder.setPrecision(result, precision); - } - - // Handle component-wise +, -, *, %, and / for all combinations of type. - // The result type of all of them is the same type as the (a) matrix operand. - // The algorithm is to: - // - break the matrix(es) into vectors - // - smear any scalar to a vector - // - do vector operations - // - make a matrix out the vector results - switch (op) { - case spv::OpFAdd: - case spv::OpFSub: - case spv::OpFDiv: - case spv::OpFMod: - case spv::OpFMul: - { - // one time set up... - bool leftMat = builder.isMatrix(left); - bool rightMat = builder.isMatrix(right); - unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right); - int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right); - spv::Id scalarType = builder.getScalarTypeId(typeId); - spv::Id vecType = builder.makeVectorType(scalarType, numRows); - std::vector results; - spv::Id smearVec = spv::NoResult; - if (builder.isScalar(left)) - smearVec = builder.smearScalar(precision, left, vecType); - else if (builder.isScalar(right)) - smearVec = builder.smearScalar(precision, right, vecType); - - // do each vector op - for (unsigned int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec; - spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec; - spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec); - addDecoration(result, noContraction); - results.push_back(builder.setPrecision(result, precision)); - } - - // put the pieces together - return builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision); - } - default: - assert(0); - return spv::NoResult; - } -} - -spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy) -{ - spv::Op unaryOp = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; -#ifdef AMD_EXTENSIONS - bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64 || typeProxy == glslang::EbtUint16; - bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16; -#else - bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64; - bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble; -#endif - - switch (op) { - case glslang::EOpNegative: - if (isFloat) { - unaryOp = spv::OpFNegate; - if (builder.isMatrixType(typeId)) - return createUnaryMatrixOperation(unaryOp, precision, noContraction, typeId, operand, typeProxy); - } else - unaryOp = spv::OpSNegate; - break; - - case glslang::EOpLogicalNot: - case glslang::EOpVectorLogicalNot: - unaryOp = spv::OpLogicalNot; - break; - case glslang::EOpBitwiseNot: - unaryOp = spv::OpNot; - break; - - case glslang::EOpDeterminant: - libCall = spv::GLSLstd450Determinant; - break; - case glslang::EOpMatrixInverse: - libCall = spv::GLSLstd450MatrixInverse; - break; - case glslang::EOpTranspose: - unaryOp = spv::OpTranspose; - break; - - case glslang::EOpRadians: - libCall = spv::GLSLstd450Radians; - break; - case glslang::EOpDegrees: - libCall = spv::GLSLstd450Degrees; - break; - case glslang::EOpSin: - libCall = spv::GLSLstd450Sin; - break; - case glslang::EOpCos: - libCall = spv::GLSLstd450Cos; - break; - case glslang::EOpTan: - libCall = spv::GLSLstd450Tan; - break; - case glslang::EOpAcos: - libCall = spv::GLSLstd450Acos; - break; - case glslang::EOpAsin: - libCall = spv::GLSLstd450Asin; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan; - break; - - case glslang::EOpAcosh: - libCall = spv::GLSLstd450Acosh; - break; - case glslang::EOpAsinh: - libCall = spv::GLSLstd450Asinh; - break; - case glslang::EOpAtanh: - libCall = spv::GLSLstd450Atanh; - break; - case glslang::EOpTanh: - libCall = spv::GLSLstd450Tanh; - break; - case glslang::EOpCosh: - libCall = spv::GLSLstd450Cosh; - break; - case glslang::EOpSinh: - libCall = spv::GLSLstd450Sinh; - break; - - case glslang::EOpLength: - libCall = spv::GLSLstd450Length; - break; - case glslang::EOpNormalize: - libCall = spv::GLSLstd450Normalize; - break; - - case glslang::EOpExp: - libCall = spv::GLSLstd450Exp; - break; - case glslang::EOpLog: - libCall = spv::GLSLstd450Log; - break; - case glslang::EOpExp2: - libCall = spv::GLSLstd450Exp2; - break; - case glslang::EOpLog2: - libCall = spv::GLSLstd450Log2; - break; - case glslang::EOpSqrt: - libCall = spv::GLSLstd450Sqrt; - break; - case glslang::EOpInverseSqrt: - libCall = spv::GLSLstd450InverseSqrt; - break; - - case glslang::EOpFloor: - libCall = spv::GLSLstd450Floor; - break; - case glslang::EOpTrunc: - libCall = spv::GLSLstd450Trunc; - break; - case glslang::EOpRound: - libCall = spv::GLSLstd450Round; - break; - case glslang::EOpRoundEven: - libCall = spv::GLSLstd450RoundEven; - break; - case glslang::EOpCeil: - libCall = spv::GLSLstd450Ceil; - break; - case glslang::EOpFract: - libCall = spv::GLSLstd450Fract; - break; - - case glslang::EOpIsNan: - unaryOp = spv::OpIsNan; - break; - case glslang::EOpIsInf: - unaryOp = spv::OpIsInf; - break; - case glslang::EOpIsFinite: - unaryOp = spv::OpIsFinite; - break; - - case glslang::EOpFloatBitsToInt: - case glslang::EOpFloatBitsToUint: - case glslang::EOpIntBitsToFloat: - case glslang::EOpUintBitsToFloat: - case glslang::EOpDoubleBitsToInt64: - case glslang::EOpDoubleBitsToUint64: - case glslang::EOpInt64BitsToDouble: - case glslang::EOpUint64BitsToDouble: -#ifdef AMD_EXTENSIONS - case glslang::EOpFloat16BitsToInt16: - case glslang::EOpFloat16BitsToUint16: - case glslang::EOpInt16BitsToFloat16: - case glslang::EOpUint16BitsToFloat16: -#endif - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpPackSnorm2x16: - libCall = spv::GLSLstd450PackSnorm2x16; - break; - case glslang::EOpUnpackSnorm2x16: - libCall = spv::GLSLstd450UnpackSnorm2x16; - break; - case glslang::EOpPackUnorm2x16: - libCall = spv::GLSLstd450PackUnorm2x16; - break; - case glslang::EOpUnpackUnorm2x16: - libCall = spv::GLSLstd450UnpackUnorm2x16; - break; - case glslang::EOpPackHalf2x16: - libCall = spv::GLSLstd450PackHalf2x16; - break; - case glslang::EOpUnpackHalf2x16: - libCall = spv::GLSLstd450UnpackHalf2x16; - break; - case glslang::EOpPackSnorm4x8: - libCall = spv::GLSLstd450PackSnorm4x8; - break; - case glslang::EOpUnpackSnorm4x8: - libCall = spv::GLSLstd450UnpackSnorm4x8; - break; - case glslang::EOpPackUnorm4x8: - libCall = spv::GLSLstd450PackUnorm4x8; - break; - case glslang::EOpUnpackUnorm4x8: - libCall = spv::GLSLstd450UnpackUnorm4x8; - break; - case glslang::EOpPackDouble2x32: - libCall = spv::GLSLstd450PackDouble2x32; - break; - case glslang::EOpUnpackDouble2x32: - libCall = spv::GLSLstd450UnpackDouble2x32; - break; - - case glslang::EOpPackInt2x32: - case glslang::EOpUnpackInt2x32: - case glslang::EOpPackUint2x32: - case glslang::EOpUnpackUint2x32: - unaryOp = spv::OpBitcast; - break; - -#ifdef AMD_EXTENSIONS - case glslang::EOpPackInt2x16: - case glslang::EOpUnpackInt2x16: - case glslang::EOpPackUint2x16: - case glslang::EOpUnpackUint2x16: - case glslang::EOpPackInt4x16: - case glslang::EOpUnpackInt4x16: - case glslang::EOpPackUint4x16: - case glslang::EOpUnpackUint4x16: - case glslang::EOpPackFloat2x16: - case glslang::EOpUnpackFloat2x16: - unaryOp = spv::OpBitcast; - break; -#endif - - case glslang::EOpDPdx: - unaryOp = spv::OpDPdx; - break; - case glslang::EOpDPdy: - unaryOp = spv::OpDPdy; - break; - case glslang::EOpFwidth: - unaryOp = spv::OpFwidth; - break; - case glslang::EOpDPdxFine: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdxFine; - break; - case glslang::EOpDPdyFine: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdyFine; - break; - case glslang::EOpFwidthFine: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpFwidthFine; - break; - case glslang::EOpDPdxCoarse: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdxCoarse; - break; - case glslang::EOpDPdyCoarse: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpDPdyCoarse; - break; - case glslang::EOpFwidthCoarse: - builder.addCapability(spv::CapabilityDerivativeControl); - unaryOp = spv::OpFwidthCoarse; - break; - case glslang::EOpInterpolateAtCentroid: - builder.addCapability(spv::CapabilityInterpolationFunction); - libCall = spv::GLSLstd450InterpolateAtCentroid; - break; - case glslang::EOpAny: - unaryOp = spv::OpAny; - break; - case glslang::EOpAll: - unaryOp = spv::OpAll; - break; - - case glslang::EOpAbs: - if (isFloat) - libCall = spv::GLSLstd450FAbs; - else - libCall = spv::GLSLstd450SAbs; - break; - case glslang::EOpSign: - if (isFloat) - libCall = spv::GLSLstd450FSign; - else - libCall = spv::GLSLstd450SSign; - break; - - case glslang::EOpAtomicCounterIncrement: - case glslang::EOpAtomicCounterDecrement: - case glslang::EOpAtomicCounter: - { - // Handle all of the atomics in one place, in createAtomicOperation() - std::vector operands; - operands.push_back(operand); - return createAtomicOperation(op, precision, typeId, operands, typeProxy); - } - - case glslang::EOpBitFieldReverse: - unaryOp = spv::OpBitReverse; - break; - case glslang::EOpBitCount: - unaryOp = spv::OpBitCount; - break; - case glslang::EOpFindLSB: - libCall = spv::GLSLstd450FindILsb; - break; - case glslang::EOpFindMSB: - if (isUnsigned) - libCall = spv::GLSLstd450FindUMsb; - else - libCall = spv::GLSLstd450FindSMsb; - break; - - case glslang::EOpBallot: - case glslang::EOpReadFirstInvocation: - case glslang::EOpAnyInvocation: - case glslang::EOpAllInvocations: - case glslang::EOpAllInvocationsEqual: -#ifdef AMD_EXTENSIONS - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: -#endif - { - std::vector operands; - operands.push_back(operand); - return createInvocationsOperation(op, typeId, operands, typeProxy); - } - -#ifdef AMD_EXTENSIONS - case glslang::EOpMbcnt: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::MbcntAMD; - break; - - case glslang::EOpCubeFaceIndex: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceIndexAMD; - break; - - case glslang::EOpCubeFaceCoord: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceCoordAMD; - break; -#endif - - default: - return 0; - } - - spv::Id id; - if (libCall >= 0) { - std::vector args; - args.push_back(operand); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, args); - } else { - id = builder.createUnaryOp(unaryOp, typeId, operand); - } - - addDecoration(id, noContraction); - return builder.setPrecision(id, precision); -} - -// Create a unary operation on a matrix -spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType /* typeProxy */) -{ - // Handle unary operations vector by vector. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the matrix into vectors - // - apply the operation to each vector - // - make a matrix out the vector results - - // get the types sorted out - int numCols = builder.getNumColumns(operand); - int numRows = builder.getNumRows(operand); - spv::Id srcVecType = builder.makeVectorType(builder.getScalarTypeId(builder.getTypeId(operand)), numRows); - spv::Id destVecType = builder.makeVectorType(builder.getScalarTypeId(typeId), numRows); - std::vector results; - - // do each vector op - for (int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes); - spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec); - addDecoration(destVec, noContraction); - results.push_back(builder.setPrecision(destVec, precision)); - } - - // put the pieces together - return builder.setPrecision(builder.createCompositeConstruct(typeId, results), precision); -} - -spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id destType, spv::Id operand, glslang::TBasicType typeProxy) -{ - spv::Op convOp = spv::OpNop; - spv::Id zero = 0; - spv::Id one = 0; - spv::Id type = 0; - - int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0; - - switch (op) { - case glslang::EOpConvIntToBool: - case glslang::EOpConvUintToBool: - case glslang::EOpConvInt64ToBool: - case glslang::EOpConvUint64ToBool: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvInt16ToBool: - case glslang::EOpConvUint16ToBool: -#endif - if (op == glslang::EOpConvInt64ToBool || op == glslang::EOpConvUint64ToBool) - zero = builder.makeUint64Constant(0); -#ifdef AMD_EXTENSIONS - else if (op == glslang::EOpConvInt16ToBool || op == glslang::EOpConvUint16ToBool) - zero = builder.makeUint16Constant(0); -#endif - else - zero = builder.makeUintConstant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - - case glslang::EOpConvFloatToBool: - zero = builder.makeFloatConstant(0.0F); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - - case glslang::EOpConvDoubleToBool: - zero = builder.makeDoubleConstant(0.0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); - -#ifdef AMD_EXTENSIONS - case glslang::EOpConvFloat16ToBool: - zero = builder.makeFloat16Constant(0.0F); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFOrdNotEqual, destType, operand, zero); -#endif - - case glslang::EOpConvBoolToFloat: - convOp = spv::OpSelect; - zero = builder.makeFloatConstant(0.0F); - one = builder.makeFloatConstant(1.0F); - break; - - case glslang::EOpConvBoolToDouble: - convOp = spv::OpSelect; - zero = builder.makeDoubleConstant(0.0); - one = builder.makeDoubleConstant(1.0); - break; - -#ifdef AMD_EXTENSIONS - case glslang::EOpConvBoolToFloat16: - convOp = spv::OpSelect; - zero = builder.makeFloat16Constant(0.0F); - one = builder.makeFloat16Constant(1.0F); - break; -#endif - - case glslang::EOpConvBoolToInt: - case glslang::EOpConvBoolToInt64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvBoolToInt16: -#endif - if (op == glslang::EOpConvBoolToInt64) - zero = builder.makeInt64Constant(0); -#ifdef AMD_EXTENSIONS - else if (op == glslang::EOpConvBoolToInt16) - zero = builder.makeInt16Constant(0); -#endif - else - zero = builder.makeIntConstant(0); - - if (op == glslang::EOpConvBoolToInt64) - one = builder.makeInt64Constant(1); -#ifdef AMD_EXTENSIONS - else if (op == glslang::EOpConvBoolToInt16) - one = builder.makeInt16Constant(1); -#endif - else - one = builder.makeIntConstant(1); - - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToUint: - case glslang::EOpConvBoolToUint64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvBoolToUint16: -#endif - if (op == glslang::EOpConvBoolToUint64) - zero = builder.makeUint64Constant(0); -#ifdef AMD_EXTENSIONS - else if (op == glslang::EOpConvBoolToUint16) - zero = builder.makeUint16Constant(0); -#endif - else - zero = builder.makeUintConstant(0); - - if (op == glslang::EOpConvBoolToUint64) - one = builder.makeUint64Constant(1); -#ifdef AMD_EXTENSIONS - else if (op == glslang::EOpConvBoolToUint16) - one = builder.makeUint16Constant(1); -#endif - else - one = builder.makeUintConstant(1); - - convOp = spv::OpSelect; - break; - - case glslang::EOpConvIntToFloat: - case glslang::EOpConvIntToDouble: - case glslang::EOpConvInt64ToFloat: - case glslang::EOpConvInt64ToDouble: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvInt16ToFloat: - case glslang::EOpConvInt16ToDouble: - case glslang::EOpConvInt16ToFloat16: - case glslang::EOpConvIntToFloat16: - case glslang::EOpConvInt64ToFloat16: -#endif - convOp = spv::OpConvertSToF; - break; - - case glslang::EOpConvUintToFloat: - case glslang::EOpConvUintToDouble: - case glslang::EOpConvUint64ToFloat: - case glslang::EOpConvUint64ToDouble: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvUint16ToFloat: - case glslang::EOpConvUint16ToDouble: - case glslang::EOpConvUint16ToFloat16: - case glslang::EOpConvUintToFloat16: - case glslang::EOpConvUint64ToFloat16: -#endif - convOp = spv::OpConvertUToF; - break; - - case glslang::EOpConvDoubleToFloat: - case glslang::EOpConvFloatToDouble: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvDoubleToFloat16: - case glslang::EOpConvFloat16ToDouble: - case glslang::EOpConvFloatToFloat16: - case glslang::EOpConvFloat16ToFloat: -#endif - convOp = spv::OpFConvert; - if (builder.isMatrixType(destType)) - return createUnaryMatrixOperation(convOp, precision, noContraction, destType, operand, typeProxy); - break; - - case glslang::EOpConvFloatToInt: - case glslang::EOpConvDoubleToInt: - case glslang::EOpConvFloatToInt64: - case glslang::EOpConvDoubleToInt64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvFloatToInt16: - case glslang::EOpConvDoubleToInt16: - case glslang::EOpConvFloat16ToInt16: - case glslang::EOpConvFloat16ToInt: - case glslang::EOpConvFloat16ToInt64: -#endif - convOp = spv::OpConvertFToS; - break; - - case glslang::EOpConvUintToInt: - case glslang::EOpConvIntToUint: - case glslang::EOpConvUint64ToInt64: - case glslang::EOpConvInt64ToUint64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvUint16ToInt16: - case glslang::EOpConvInt16ToUint16: -#endif - if (builder.isInSpecConstCodeGenMode()) { - // Build zero scalar or vector for OpIAdd. - if (op == glslang::EOpConvUint64ToInt64 || op == glslang::EOpConvInt64ToUint64) - zero = builder.makeUint64Constant(0); -#ifdef AMD_EXTENSIONS - else if (op == glslang::EOpConvUint16ToInt16 || op == glslang::EOpConvInt16ToUint16) - zero = builder.makeUint16Constant(0); -#endif - else - zero = builder.makeUintConstant(0); - - zero = makeSmearedConstant(zero, vectorSize); - // Use OpIAdd, instead of OpBitcast to do the conversion when - // generating for OpSpecConstantOp instruction. - return builder.createBinOp(spv::OpIAdd, destType, operand, zero); - } - // For normal run-time conversion instruction, use OpBitcast. - convOp = spv::OpBitcast; - break; - - case glslang::EOpConvFloatToUint: - case glslang::EOpConvDoubleToUint: - case glslang::EOpConvFloatToUint64: - case glslang::EOpConvDoubleToUint64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvFloatToUint16: - case glslang::EOpConvDoubleToUint16: - case glslang::EOpConvFloat16ToUint16: - case glslang::EOpConvFloat16ToUint: - case glslang::EOpConvFloat16ToUint64: -#endif - convOp = spv::OpConvertFToU; - break; - - case glslang::EOpConvIntToInt64: - case glslang::EOpConvInt64ToInt: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvIntToInt16: - case glslang::EOpConvInt16ToInt: - case glslang::EOpConvInt64ToInt16: - case glslang::EOpConvInt16ToInt64: -#endif - convOp = spv::OpSConvert; - break; - - case glslang::EOpConvUintToUint64: - case glslang::EOpConvUint64ToUint: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvUintToUint16: - case glslang::EOpConvUint16ToUint: - case glslang::EOpConvUint64ToUint16: - case glslang::EOpConvUint16ToUint64: -#endif - convOp = spv::OpUConvert; - break; - - case glslang::EOpConvIntToUint64: - case glslang::EOpConvInt64ToUint: - case glslang::EOpConvUint64ToInt: - case glslang::EOpConvUintToInt64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvInt16ToUint: - case glslang::EOpConvUintToInt16: - case glslang::EOpConvInt16ToUint64: - case glslang::EOpConvUint64ToInt16: - case glslang::EOpConvUint16ToInt: - case glslang::EOpConvIntToUint16: - case glslang::EOpConvUint16ToInt64: - case glslang::EOpConvInt64ToUint16: -#endif - // OpSConvert/OpUConvert + OpBitCast - switch (op) { - case glslang::EOpConvIntToUint64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvInt16ToUint64: -#endif - convOp = spv::OpSConvert; - type = builder.makeIntType(64); - break; - case glslang::EOpConvInt64ToUint: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvInt16ToUint: -#endif - convOp = spv::OpSConvert; - type = builder.makeIntType(32); - break; - case glslang::EOpConvUint64ToInt: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvUint16ToInt: -#endif - convOp = spv::OpUConvert; - type = builder.makeUintType(32); - break; - case glslang::EOpConvUintToInt64: -#ifdef AMD_EXTENSIONS - case glslang::EOpConvUint16ToInt64: -#endif - convOp = spv::OpUConvert; - type = builder.makeUintType(64); - break; -#ifdef AMD_EXTENSIONS - case glslang::EOpConvUintToInt16: - case glslang::EOpConvUint64ToInt16: - convOp = spv::OpUConvert; - type = builder.makeUintType(16); - break; - case glslang::EOpConvIntToUint16: - case glslang::EOpConvInt64ToUint16: - convOp = spv::OpSConvert; - type = builder.makeIntType(16); - break; -#endif - default: - assert(0); - break; - } - - if (vectorSize > 0) - type = builder.makeVectorType(type, vectorSize); - - operand = builder.createUnaryOp(convOp, type, operand); - - if (builder.isInSpecConstCodeGenMode()) { - // Build zero scalar or vector for OpIAdd. -#ifdef AMD_EXTENSIONS - if (op == glslang::EOpConvIntToUint64 || op == glslang::EOpConvUintToInt64 || - op == glslang::EOpConvInt16ToUint64 || op == glslang::EOpConvUint16ToInt64) - zero = builder.makeUint64Constant(0); - else if (op == glslang::EOpConvIntToUint16 || op == glslang::EOpConvUintToInt16 || - op == glslang::EOpConvInt64ToUint16 || op == glslang::EOpConvUint64ToInt16) - zero = builder.makeUint16Constant(0); - else - zero = builder.makeUintConstant(0); -#else - if (op == glslang::EOpConvIntToUint64 || op == glslang::EOpConvUintToInt64) - zero = builder.makeUint64Constant(0); - else - zero = builder.makeUintConstant(0); -#endif - - zero = makeSmearedConstant(zero, vectorSize); - // Use OpIAdd, instead of OpBitcast to do the conversion when - // generating for OpSpecConstantOp instruction. - return builder.createBinOp(spv::OpIAdd, destType, operand, zero); - } - // For normal run-time conversion instruction, use OpBitcast. - convOp = spv::OpBitcast; - break; - default: - break; - } - - spv::Id result = 0; - if (convOp == spv::OpNop) - return result; - - if (convOp == spv::OpSelect) { - zero = makeSmearedConstant(zero, vectorSize); - one = makeSmearedConstant(one, vectorSize); - result = builder.createTriOp(convOp, destType, operand, one, zero); - } else - result = builder.createUnaryOp(convOp, destType, operand); - - return builder.setPrecision(result, precision); -} - -spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize) -{ - if (vectorSize == 0) - return constant; - - spv::Id vectorTypeId = builder.makeVectorType(builder.getTypeId(constant), vectorSize); - std::vector components; - for (int c = 0; c < vectorSize; ++c) - components.push_back(constant); - return builder.makeCompositeConstant(vectorTypeId, components); -} - -// For glslang ops that map to SPV atomic opCodes -spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ - spv::Op opCode = spv::OpNop; - - switch (op) { - case glslang::EOpAtomicAdd: - case glslang::EOpImageAtomicAdd: - case glslang::EOpAtomicCounterAdd: - opCode = spv::OpAtomicIAdd; - break; - case glslang::EOpAtomicCounterSubtract: - opCode = spv::OpAtomicISub; - break; - case glslang::EOpAtomicMin: - case glslang::EOpImageAtomicMin: - case glslang::EOpAtomicCounterMin: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMin : spv::OpAtomicSMin; - break; - case glslang::EOpAtomicMax: - case glslang::EOpImageAtomicMax: - case glslang::EOpAtomicCounterMax: - opCode = (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) ? spv::OpAtomicUMax : spv::OpAtomicSMax; - break; - case glslang::EOpAtomicAnd: - case glslang::EOpImageAtomicAnd: - case glslang::EOpAtomicCounterAnd: - opCode = spv::OpAtomicAnd; - break; - case glslang::EOpAtomicOr: - case glslang::EOpImageAtomicOr: - case glslang::EOpAtomicCounterOr: - opCode = spv::OpAtomicOr; - break; - case glslang::EOpAtomicXor: - case glslang::EOpImageAtomicXor: - case glslang::EOpAtomicCounterXor: - opCode = spv::OpAtomicXor; - break; - case glslang::EOpAtomicExchange: - case glslang::EOpImageAtomicExchange: - case glslang::EOpAtomicCounterExchange: - opCode = spv::OpAtomicExchange; - break; - case glslang::EOpAtomicCompSwap: - case glslang::EOpImageAtomicCompSwap: - case glslang::EOpAtomicCounterCompSwap: - opCode = spv::OpAtomicCompareExchange; - break; - case glslang::EOpAtomicCounterIncrement: - opCode = spv::OpAtomicIIncrement; - break; - case glslang::EOpAtomicCounterDecrement: - opCode = spv::OpAtomicIDecrement; - break; - case glslang::EOpAtomicCounter: - opCode = spv::OpAtomicLoad; - break; - default: - assert(0); - break; - } - - if (typeProxy == glslang::EbtInt64 || typeProxy == glslang::EbtUint64) - builder.addCapability(spv::CapabilityInt64Atomics); - - // Sort out the operands - // - mapping from glslang -> SPV - // - there are extra SPV operands with no glslang source - // - compare-exchange swaps the value and comparator - // - compare-exchange has an extra memory semantics - // - EOpAtomicCounterDecrement needs a post decrement - std::vector spvAtomicOperands; // hold the spv operands - auto opIt = operands.begin(); // walk the glslang operands - spvAtomicOperands.push_back(*(opIt++)); - spvAtomicOperands.push_back(builder.makeUintConstant(spv::ScopeDevice)); // TBD: what is the correct scope? - spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone)); // TBD: what are the correct memory semantics? - if (opCode == spv::OpAtomicCompareExchange) { - // There are 2 memory semantics for compare-exchange. And the operand order of "comparator" and "new value" in GLSL - // differs from that in SPIR-V. Hence, special processing is required. - spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone)); - spvAtomicOperands.push_back(*(opIt + 1)); - spvAtomicOperands.push_back(*opIt); - opIt += 2; - } - - // Add the rest of the operands, skipping any that were dealt with above. - for (; opIt != operands.end(); ++opIt) - spvAtomicOperands.push_back(*opIt); - - spv::Id resultId = builder.createOp(opCode, typeId, spvAtomicOperands); - - // GLSL and HLSL atomic-counter decrement return post-decrement value, - // while SPIR-V returns pre-decrement value. Translate between these semantics. - if (op == glslang::EOpAtomicCounterDecrement) - resultId = builder.createBinOp(spv::OpISub, typeId, resultId, builder.makeIntConstant(1)); - - return resultId; -} - -// Create group invocation operations. -spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ -#ifdef AMD_EXTENSIONS - bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64; - bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16; -#endif - - spv::Op opCode = spv::OpNop; - std::vector spvGroupOperands; - spv::GroupOperation groupOperation = spv::GroupOperationMax; - - if (op == glslang::EOpBallot || op == glslang::EOpReadFirstInvocation || - op == glslang::EOpReadInvocation) { - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - } else if (op == glslang::EOpAnyInvocation || - op == glslang::EOpAllInvocations || - op == glslang::EOpAllInvocationsEqual) { - builder.addExtension(spv::E_SPV_KHR_subgroup_vote); - builder.addCapability(spv::CapabilitySubgroupVoteKHR); - } else { - builder.addCapability(spv::CapabilityGroups); -#ifdef AMD_EXTENSIONS - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpAddInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpAddInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform || - op == glslang::EOpAddInvocationsExclusiveScanNonUniform) - builder.addExtension(spv::E_SPV_AMD_shader_ballot); -#endif - - spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); -#ifdef AMD_EXTENSIONS - switch (op) { - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - groupOperation = spv::GroupOperationReduce; - spvGroupOperands.push_back(groupOperation); - break; - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - groupOperation = spv::GroupOperationInclusiveScan; - spvGroupOperands.push_back(groupOperation); - break; - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - groupOperation = spv::GroupOperationExclusiveScan; - spvGroupOperands.push_back(groupOperation); - break; - default: - break; - } -#endif - } - - for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) - spvGroupOperands.push_back(*opIt); - - switch (op) { - case glslang::EOpAnyInvocation: - opCode = spv::OpSubgroupAnyKHR; - break; - case glslang::EOpAllInvocations: - opCode = spv::OpSubgroupAllKHR; - break; - case glslang::EOpAllInvocationsEqual: - opCode = spv::OpSubgroupAllEqualKHR; - break; - case glslang::EOpReadInvocation: - opCode = spv::OpSubgroupReadInvocationKHR; - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - break; - case glslang::EOpReadFirstInvocation: - opCode = spv::OpSubgroupFirstInvocationKHR; - break; - case glslang::EOpBallot: - { - // NOTE: According to the spec, the result type of "OpSubgroupBallotKHR" must be a 4 component vector of 32 - // bit integer types. The GLSL built-in function "ballotARB()" assumes the maximum number of invocations in - // a subgroup is 64. Thus, we have to convert uvec4.xy to uint64_t as follow: - // - // result = Bitcast(SubgroupBallotKHR(Predicate).xy) - // - spv::Id uintType = builder.makeUintType(32); - spv::Id uvec4Type = builder.makeVectorType(uintType, 4); - spv::Id result = builder.createOp(spv::OpSubgroupBallotKHR, uvec4Type, spvGroupOperands); - - std::vector components; - components.push_back(builder.createCompositeExtract(result, uintType, 0)); - components.push_back(builder.createCompositeExtract(result, uintType, 1)); - - spv::Id uvec2Type = builder.makeVectorType(uintType, 2); - return builder.createUnaryOp(spv::OpBitcast, typeId, - builder.createCompositeConstruct(uvec2Type, components)); - } - -#ifdef AMD_EXTENSIONS - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - if (op == glslang::EOpMinInvocations || - op == glslang::EOpMinInvocationsInclusiveScan || - op == glslang::EOpMinInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMin; - else { - if (isUnsigned) - opCode = spv::OpGroupUMin; - else - opCode = spv::OpGroupSMin; - } - } else if (op == glslang::EOpMaxInvocations || - op == glslang::EOpMaxInvocationsInclusiveScan || - op == glslang::EOpMaxInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMax; - else { - if (isUnsigned) - opCode = spv::OpGroupUMax; - else - opCode = spv::OpGroupSMax; - } - } else { - if (isFloat) - opCode = spv::OpGroupFAdd; - else - opCode = spv::OpGroupIAdd; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMinNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMinNonUniformAMD; - else - opCode = spv::OpGroupSMinNonUniformAMD; - } - } - else if (op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMaxNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMaxNonUniformAMD; - else - opCode = spv::OpGroupSMaxNonUniformAMD; - } - } - else { - if (isFloat) - opCode = spv::OpGroupFAddNonUniformAMD; - else - opCode = spv::OpGroupIAddNonUniformAMD; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; -#endif - default: - logger->missingFunctionality("invocation operation"); - return spv::NoResult; - } - - assert(opCode != spv::OpNop); - return builder.createOp(opCode, typeId, spvGroupOperands); -} - -// Create group invocation operations on a vector -spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector& operands) -{ -#ifdef AMD_EXTENSIONS - assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || - op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || - op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || - op == spv::OpSubgroupReadInvocationKHR || - op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD || - op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD || - op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD); -#else - assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || - op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || - op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || - op == spv::OpSubgroupReadInvocationKHR); -#endif - - // Handle group invocation operations scalar by scalar. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the vector into scalars - // - apply the operation to each scalar - // - make a vector out the scalar results - - // get the types sorted out - int numComponents = builder.getNumComponents(operands[0]); - spv::Id scalarType = builder.getScalarTypeId(builder.getTypeId(operands[0])); - std::vector results; - - // do each scalar op - for (int comp = 0; comp < numComponents; ++comp) { - std::vector indexes; - indexes.push_back(comp); - spv::Id scalar = builder.createCompositeExtract(operands[0], scalarType, indexes); - std::vector spvGroupOperands; - if (op == spv::OpSubgroupReadInvocationKHR) { - spvGroupOperands.push_back(scalar); - spvGroupOperands.push_back(operands[1]); - } else if (op == spv::OpGroupBroadcast) { - spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); - spvGroupOperands.push_back(scalar); - spvGroupOperands.push_back(operands[1]); - } else { - spvGroupOperands.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); - spvGroupOperands.push_back(groupOperation); - spvGroupOperands.push_back(scalar); - } - - results.push_back(builder.createOp(op, scalarType, spvGroupOperands)); - } - - // put the pieces together - return builder.createCompositeConstruct(typeId, results); -} - -spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ -#ifdef AMD_EXTENSIONS - bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64 || typeProxy == glslang::EbtUint16; - bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble || typeProxy == glslang::EbtFloat16; -#else - bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64; - bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble; -#endif - - spv::Op opCode = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; - size_t consumedOperands = operands.size(); - spv::Id typeId0 = 0; - if (consumedOperands > 0) - typeId0 = builder.getTypeId(operands[0]); - spv::Id typeId1 = 0; - if (consumedOperands > 1) - typeId1 = builder.getTypeId(operands[1]); - spv::Id frexpIntType = 0; - - switch (op) { - case glslang::EOpMin: - if (isFloat) - libCall = spv::GLSLstd450FMin; - else if (isUnsigned) - libCall = spv::GLSLstd450UMin; - else - libCall = spv::GLSLstd450SMin; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpModf: - libCall = spv::GLSLstd450Modf; - break; - case glslang::EOpMax: - if (isFloat) - libCall = spv::GLSLstd450FMax; - else if (isUnsigned) - libCall = spv::GLSLstd450UMax; - else - libCall = spv::GLSLstd450SMax; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpPow: - libCall = spv::GLSLstd450Pow; - break; - case glslang::EOpDot: - opCode = spv::OpDot; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan2; - break; - - case glslang::EOpClamp: - if (isFloat) - libCall = spv::GLSLstd450FClamp; - else if (isUnsigned) - libCall = spv::GLSLstd450UClamp; - else - libCall = spv::GLSLstd450SClamp; - builder.promoteScalar(precision, operands.front(), operands[1]); - builder.promoteScalar(precision, operands.front(), operands[2]); - break; - case glslang::EOpMix: - if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) { - assert(isFloat); - libCall = spv::GLSLstd450FMix; - } else { - opCode = spv::OpSelect; - std::swap(operands.front(), operands.back()); - } - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpStep: - libCall = spv::GLSLstd450Step; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpSmoothStep: - libCall = spv::GLSLstd450SmoothStep; - builder.promoteScalar(precision, operands[0], operands[2]); - builder.promoteScalar(precision, operands[1], operands[2]); - break; - - case glslang::EOpDistance: - libCall = spv::GLSLstd450Distance; - break; - case glslang::EOpCross: - libCall = spv::GLSLstd450Cross; - break; - case glslang::EOpFaceForward: - libCall = spv::GLSLstd450FaceForward; - break; - case glslang::EOpReflect: - libCall = spv::GLSLstd450Reflect; - break; - case glslang::EOpRefract: - libCall = spv::GLSLstd450Refract; - break; - case glslang::EOpInterpolateAtSample: - builder.addCapability(spv::CapabilityInterpolationFunction); - libCall = spv::GLSLstd450InterpolateAtSample; - break; - case glslang::EOpInterpolateAtOffset: - builder.addCapability(spv::CapabilityInterpolationFunction); - libCall = spv::GLSLstd450InterpolateAtOffset; - break; - case glslang::EOpAddCarry: - opCode = spv::OpIAddCarry; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpSubBorrow: - opCode = spv::OpISubBorrow; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpUMulExtended: - opCode = spv::OpUMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpIMulExtended: - opCode = spv::OpSMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpBitfieldExtract: - if (isUnsigned) - opCode = spv::OpBitFieldUExtract; - else - opCode = spv::OpBitFieldSExtract; - break; - case glslang::EOpBitfieldInsert: - opCode = spv::OpBitFieldInsert; - break; - - case glslang::EOpFma: - libCall = spv::GLSLstd450Fma; - break; - case glslang::EOpFrexp: - { - libCall = spv::GLSLstd450FrexpStruct; - assert(builder.isPointerType(typeId1)); - typeId1 = builder.getContainedTypeId(typeId1); -#ifdef AMD_EXTENSIONS - int width = builder.getScalarTypeWidth(typeId1); -#else - int width = 32; -#endif - if (builder.getNumComponents(operands[0]) == 1) - frexpIntType = builder.makeIntegerType(width, true); - else - frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), builder.getNumComponents(operands[0])); - typeId = builder.makeStructResultType(typeId0, frexpIntType); - consumedOperands = 1; - } - break; - case glslang::EOpLdexp: - libCall = spv::GLSLstd450Ldexp; - break; - - case glslang::EOpReadInvocation: - return createInvocationsOperation(op, typeId, operands, typeProxy); - -#ifdef AMD_EXTENSIONS - case glslang::EOpSwizzleInvocations: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsAMD; - break; - case glslang::EOpSwizzleInvocationsMasked: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsMaskedAMD; - break; - case glslang::EOpWriteInvocation: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::WriteInvocationAMD; - break; - - case glslang::EOpMin3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMin3AMD; - else { - if (isUnsigned) - libCall = spv::UMin3AMD; - else - libCall = spv::SMin3AMD; - } - break; - case glslang::EOpMax3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMax3AMD; - else { - if (isUnsigned) - libCall = spv::UMax3AMD; - else - libCall = spv::SMax3AMD; - } - break; - case glslang::EOpMid3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMid3AMD; - else { - if (isUnsigned) - libCall = spv::UMid3AMD; - else - libCall = spv::SMid3AMD; - } - break; - - case glslang::EOpInterpolateAtVertex: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - libCall = spv::InterpolateAtVertexAMD; - break; -#endif - - default: - return 0; - } - - spv::Id id = 0; - if (libCall >= 0) { - // Use an extended instruction from the standard library. - // Construct the call arguments, without modifying the original operands vector. - // We might need the remaining arguments, e.g. in the EOpFrexp case. - std::vector callArguments(operands.begin(), operands.begin() + consumedOperands); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, callArguments); - } else { - switch (consumedOperands) { - case 0: - // should all be handled by visitAggregate and createNoArgOperation - assert(0); - return 0; - case 1: - // should all be handled by createUnaryOperation - assert(0); - return 0; - case 2: - id = builder.createBinOp(opCode, typeId, operands[0], operands[1]); - break; - default: - // anything 3 or over doesn't have l-value operands, so all should be consumed - assert(consumedOperands == operands.size()); - id = builder.createOp(opCode, typeId, operands); - break; - } - } - - // Decode the return types that were structures - switch (op) { - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - id = builder.createCompositeExtract(id, typeId0, 0); - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]); - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - break; - case glslang::EOpFrexp: - { - assert(operands.size() == 2); - if (builder.isFloatType(builder.getScalarTypeId(typeId1))) { - // "exp" is floating-point type (from HLSL intrinsic) - spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1); - member1 = builder.createUnaryOp(spv::OpConvertSToF, typeId1, member1); - builder.createStore(member1, operands[1]); - } else - // "exp" is integer type (from GLSL built-in function) - builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]); - id = builder.createCompositeExtract(id, typeId0, 0); - } - break; - default: - break; - } - - return builder.setPrecision(id, precision); -} - -// Intrinsics with no arguments (or no return value, and no precision). -spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId) -{ - // TODO: get the barrier operands correct - - switch (op) { - case glslang::EOpEmitVertex: - builder.createNoResultOp(spv::OpEmitVertex); - return 0; - case glslang::EOpEndPrimitive: - builder.createNoResultOp(spv::OpEndPrimitive); - return 0; - case glslang::EOpBarrier: - if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeInvocation, spv::MemorySemanticsMaskNone); - // TODO: prefer the following, when available: - // builder.createControlBarrier(spv::ScopePatch, spv::ScopePatch, - // spv::MemorySemanticsPatchMask | - // spv::MemorySemanticsAcquireReleaseMask); - } else { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - } - return 0; - case glslang::EOpMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierAtomicCounter: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAtomicCounterMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierBuffer: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierImage: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierShared: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpGroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpAllMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, - spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; -#ifdef AMD_EXTENSIONS - case glslang::EOpTime: - { - std::vector args; // Dummy arguments - spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args); - return builder.setPrecision(id, precision); - } -#endif - default: - logger->missingFunctionality("unknown operation with no arguments"); - return 0; - } -} - -spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol) -{ - auto iter = symbolValues.find(symbol->getId()); - spv::Id id; - if (symbolValues.end() != iter) { - id = iter->second; - return id; - } - - // it was not found, create it - id = createSpvVariable(symbol); - symbolValues[symbol->getId()] = id; - - if (symbol->getBasicType() != glslang::EbtBlock) { - addDecoration(id, TranslatePrecisionDecoration(symbol->getType())); - addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier())); - addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier())); - if (symbol->getType().getQualifier().hasSpecConstantId()) - addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId); - if (symbol->getQualifier().hasIndex()) - builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex); - if (symbol->getQualifier().hasComponent()) - builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent); - // atomic counters use this: - if (symbol->getQualifier().hasOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset); - } - - if (symbol->getQualifier().hasLocation()) - builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation); - addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier())); - if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { - builder.addCapability(spv::CapabilityGeometryStreams); - builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream); - } - if (symbol->getQualifier().hasSet()) - builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet); - else if (IsDescriptorResource(symbol->getType())) { - // default to 0 - builder.addDecoration(id, spv::DecorationDescriptorSet, 0); - } - if (symbol->getQualifier().hasBinding()) - builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding); - if (symbol->getQualifier().hasAttachment()) - builder.addDecoration(id, spv::DecorationInputAttachmentIndex, symbol->getQualifier().layoutAttachment); - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - if (symbol->getQualifier().hasXfbStride()) - builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride); - if (symbol->getQualifier().hasXfbBuffer()) { - builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer); - unsigned stride = glslangIntermediate->getXfbStride(symbol->getQualifier().layoutXfbBuffer); - if (stride != glslang::TQualifier::layoutXfbStrideEnd) - builder.addDecoration(id, spv::DecorationXfbStride, stride); - } - if (symbol->getQualifier().hasXfbOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset); - } - - if (symbol->getType().isImage()) { - std::vector memory; - TranslateMemoryDecoration(symbol->getType().getQualifier(), memory); - for (unsigned int i = 0; i < memory.size(); ++i) - addDecoration(id, memory[i]); - } - - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); - if (builtIn != spv::BuiltInMax) - addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); - -#ifdef NV_EXTENSIONS - if (builtIn == spv::BuiltInSampleMask) { - spv::Decoration decoration; - // GL_NV_sample_mask_override_coverage extension - if (glslangIntermediate->getLayoutOverrideCoverage()) - decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV; - else - decoration = (spv::Decoration)spv::DecorationMax; - addDecoration(id, decoration); - if (decoration != spv::DecorationMax) { - builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage); - } - } - else if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (symbol->getQualifier().layoutViewportRelative) { - addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048) { - addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, symbol->getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - - if (symbol->getQualifier().layoutPassthrough) { - addDecoration(id, spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } -#endif - - return id; -} - -// If 'dec' is valid, add no-operand decoration to an object -void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec) -{ - if (dec != spv::DecorationMax) - builder.addDecoration(id, dec); -} - -// If 'dec' is valid, add a one-operand decoration to an object -void TGlslangToSpvTraverser::addDecoration(spv::Id id, spv::Decoration dec, unsigned value) -{ - if (dec != spv::DecorationMax) - builder.addDecoration(id, dec, value); -} - -// If 'dec' is valid, add a no-operand decoration to a struct member -void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec) -{ - if (dec != spv::DecorationMax) - builder.addMemberDecoration(id, (unsigned)member, dec); -} - -// If 'dec' is valid, add a one-operand decoration to a struct member -void TGlslangToSpvTraverser::addMemberDecoration(spv::Id id, int member, spv::Decoration dec, unsigned value) -{ - if (dec != spv::DecorationMax) - builder.addMemberDecoration(id, (unsigned)member, dec, value); -} - -// Make a full tree of instructions to build a SPIR-V specialization constant, -// or regular constant if possible. -// -// TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though -// -// Recursively walk the nodes. The nodes form a tree whose leaves are -// regular constants, which themselves are trees that createSpvConstant() -// recursively walks. So, this function walks the "top" of the tree: -// - emit specialization constant-building instructions for specConstant -// - when running into a non-spec-constant, switch to createSpvConstant() -spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node) -{ - assert(node.getQualifier().isConstant()); - - // Handle front-end constants first (non-specialization constants). - if (! node.getQualifier().specConstant) { - // hand off to the non-spec-constant path - assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); - int nextConst = 0; - return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), - nextConst, false); - } - - // We now know we have a specialization constant to build - - // gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants, - // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ... - if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) - addDecoration(dimConstId.back(), spv::DecorationSpecId, glslangIntermediate->getLocalSizeSpecId(dim)); - } - return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); - } - - // An AST node labelled as specialization constant should be a symbol node. - // Its initializer should either be a sub tree with constant nodes, or a constant union array. - if (auto* sn = node.getAsSymbolNode()) { - if (auto* sub_tree = sn->getConstSubtree()) { - // Traverse the constant constructor sub tree like generating normal run-time instructions. - // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard - // will set the builder into spec constant op instruction generating mode. - sub_tree->traverse(this); - return accessChainLoad(sub_tree->getType()); - } else if (auto* const_union_array = &sn->getConstArray()){ - int nextConst = 0; - spv::Id id = createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true); - builder.addName(id, sn->getName().c_str()); - return id; - } - } - - // Neither a front-end constant node, nor a specialization constant node with constant union array or - // constant sub tree as initializer. - logger->missingFunctionality("Neither a front-end constant nor a spec constant."); - exit(1); - return spv::NoResult; -} - -// Use 'consts' as the flattened glslang source of scalar constants to recursively -// build the aggregate SPIR-V constant. -// -// If there are not enough elements present in 'consts', 0 will be substituted; -// an empty 'consts' can be used to create a fully zeroed SPIR-V constant. -// -spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) -{ - // vector of constants for SPIR-V - std::vector spvConsts; - - // Type is used for struct and array constants - spv::Id typeId = convertGlslangToSpvType(glslangType); - - if (glslangType.isArray()) { - glslang::TType elementType(glslangType, 0); - for (int i = 0; i < glslangType.getOuterArraySize(); ++i) - spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false)); - } else if (glslangType.isMatrix()) { - glslang::TType vectorType(glslangType, 0); - for (int col = 0; col < glslangType.getMatrixCols(); ++col) - spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false)); - } else if (glslangType.getStruct()) { - glslang::TVector::const_iterator iter; - for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) - spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); - } else if (glslangType.getVectorSize() > 1) { - for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { - bool zero = nextConst >= consts.size(); - switch (glslangType.getBasicType()) { - case glslang::EbtInt: - spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst())); - break; - case glslang::EbtUint: - spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst())); - break; - case glslang::EbtInt64: - spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const())); - break; - case glslang::EbtUint64: - spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const())); - break; -#ifdef AMD_EXTENSIONS - case glslang::EbtInt16: - spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : (short)consts[nextConst].getIConst())); - break; - case glslang::EbtUint16: - spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : (unsigned short)consts[nextConst].getUConst())); - break; -#endif - case glslang::EbtFloat: - spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; - case glslang::EbtDouble: - spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst())); - break; -#ifdef AMD_EXTENSIONS - case glslang::EbtFloat16: - spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; -#endif - case glslang::EbtBool: - spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst())); - break; - default: - assert(0); - break; - } - ++nextConst; - } - } else { - // we have a non-aggregate (scalar) constant - bool zero = nextConst >= consts.size(); - spv::Id scalar = 0; - switch (glslangType.getBasicType()) { - case glslang::EbtInt: - scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant); - break; - case glslang::EbtUint: - scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant); - break; - case glslang::EbtInt64: - scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant); - break; - case glslang::EbtUint64: - scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); - break; -#ifdef AMD_EXTENSIONS - case glslang::EbtInt16: - scalar = builder.makeInt16Constant(zero ? 0 : (short)consts[nextConst].getIConst(), specConstant); - break; - case glslang::EbtUint16: - scalar = builder.makeUint16Constant(zero ? 0 : (unsigned short)consts[nextConst].getUConst(), specConstant); - break; -#endif - case glslang::EbtFloat: - scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtDouble: - scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant); - break; -#ifdef AMD_EXTENSIONS - case glslang::EbtFloat16: - scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; -#endif - case glslang::EbtBool: - scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant); - break; - default: - assert(0); - break; - } - ++nextConst; - return scalar; - } - - return builder.makeCompositeConstant(typeId, spvConsts); -} - -// Return true if the node is a constant or symbol whose reading has no -// non-trivial observable cost or effect. -bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) -{ - // don't know what this is - if (node == nullptr) - return false; - - // a constant is safe - if (node->getAsConstantUnion() != nullptr) - return true; - - // not a symbol means non-trivial - if (node->getAsSymbolNode() == nullptr) - return false; - - // a symbol, depends on what's being read - switch (node->getType().getQualifier().storage) { - case glslang::EvqTemporary: - case glslang::EvqGlobal: - case glslang::EvqIn: - case glslang::EvqInOut: - case glslang::EvqConst: - case glslang::EvqConstReadOnly: - case glslang::EvqUniform: - return true; - default: - return false; - } -} - -// A node is trivial if it is a single operation with no side effects. -// HLSL (and/or vectors) are always trivial, as it does not short circuit. -// Otherwise, error on the side of saying non-trivial. -// Return true if trivial. -bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node) -{ - if (node == nullptr) - return false; - - // count non scalars as trivial, as well as anything coming from HLSL - if (! node->getType().isScalarOrVec1() || glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return true; - - // symbols and constants are trivial - if (isTrivialLeaf(node)) - return true; - - // otherwise, it needs to be a simple operation or one or two leaf nodes - - // not a simple operation - const glslang::TIntermBinary* binaryNode = node->getAsBinaryNode(); - const glslang::TIntermUnary* unaryNode = node->getAsUnaryNode(); - if (binaryNode == nullptr && unaryNode == nullptr) - return false; - - // not on leaf nodes - if (binaryNode && (! isTrivialLeaf(binaryNode->getLeft()) || ! isTrivialLeaf(binaryNode->getRight()))) - return false; - - if (unaryNode && ! isTrivialLeaf(unaryNode->getOperand())) { - return false; - } - - switch (node->getAsOperator()->getOp()) { - case glslang::EOpLogicalNot: - case glslang::EOpConvIntToBool: - case glslang::EOpConvUintToBool: - case glslang::EOpConvFloatToBool: - case glslang::EOpConvDoubleToBool: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - case glslang::EOpLogicalXor: - case glslang::EOpAny: - case glslang::EOpAll: - return true; - default: - return false; - } -} - -// Emit short-circuiting code, where 'right' is never evaluated unless -// the left side is true (for &&) or false (for ||). -spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, glslang::TIntermTyped& right) -{ - spv::Id boolTypeId = builder.makeBoolType(); - - // emit left operand - builder.clearAccessChain(); - left.traverse(this); - spv::Id leftId = accessChainLoad(left.getType()); - - // Operands to accumulate OpPhi operands - std::vector phiOperands; - // accumulate left operand's phi information - phiOperands.push_back(leftId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // Make the two kinds of operation symmetric with a "!" - // || => emit "if (! left) result = right" - // && => emit "if ( left) result = right" - // - // TODO: this runtime "not" for || could be avoided by adding functionality - // to 'builder' to have an "else" without an "then" - if (op == glslang::EOpLogicalOr) - leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId); - - // make an "if" based on the left value - spv::Builder::If ifBuilder(leftId, spv::SelectionControlMaskNone, builder); - - // emit right operand as the "then" part of the "if" - builder.clearAccessChain(); - right.traverse(this); - spv::Id rightId = accessChainLoad(right.getType()); - - // accumulate left operand's phi information - phiOperands.push_back(rightId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // finish the "if" - ifBuilder.makeEndIf(); - - // phi together the two results - return builder.createOp(spv::OpPhi, boolTypeId, phiOperands); -} - -#ifdef AMD_EXTENSIONS -// Return type Id of the imported set of extended instructions corresponds to the name. -// Import this set if it has not been imported yet. -spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name) -{ - if (extBuiltinMap.find(name) != extBuiltinMap.end()) - return extBuiltinMap[name]; - else { - builder.addExtension(name); - spv::Id extBuiltins = builder.import(name); - extBuiltinMap[name] = extBuiltins; - return extBuiltins; - } -} -#endif - -}; // end anonymous namespace - -namespace glslang { - -void GetSpirvVersion(std::string& version) -{ - const int bufSize = 100; - char buf[bufSize]; - snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision); - version = buf; -} - -// For low-order part of the generator's magic number. Bump up -// when there is a change in the style (e.g., if SSA form changes, -// or a different instruction sequence to do something gets used). -int GetSpirvGeneratorVersion() -{ - // return 1; // start - // return 2; // EOpAtomicCounterDecrement gets a post decrement, to map between GLSL -> SPIR-V - // return 3; // change/correct barrier-instruction operands, to match memory model group decisions - return 4; // some deeper access chains: for dynamic vector component, and local Boolean component -} - -// Write SPIR-V out to a binary file -void OutputSpvBin(const std::vector& spirv, const char* baseName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) - printf("ERROR: Failed to open file: %s\n", baseName); - for (int i = 0; i < (int)spirv.size(); ++i) { - unsigned int word = spirv[i]; - out.write((const char*)&word, 4); - } - out.close(); -} - -// Write SPIR-V out to a text file with 32-bit hexadecimal words -void OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) - printf("ERROR: Failed to open file: %s\n", baseName); - out << "\t// " GLSLANG_REVISION " " GLSLANG_DATE << std::endl; - if (varName != nullptr) { - out << "\t #pragma once" << std::endl; - out << "const uint32_t " << varName << "[] = {" << std::endl; - } - const int WORDS_PER_LINE = 8; - for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) { - out << "\t"; - for (int j = 0; j < WORDS_PER_LINE && i + j < (int)spirv.size(); ++j) { - const unsigned int word = spirv[i + j]; - out << "0x" << std::hex << std::setw(8) << std::setfill('0') << word; - if (i + j + 1 < (int)spirv.size()) { - out << ","; - } - } - out << std::endl; - } - if (varName != nullptr) { - out << "};"; - } - out.close(); -} - -#ifdef ENABLE_OPT -void errHandler(const std::string& str) { - std::cerr << str << std::endl; -} -#endif - -// -// Set up the glslang traversal -// -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, SpvOptions* options) -{ - spv::SpvBuildLogger logger; - GlslangToSpv(intermediate, spirv, &logger, options); -} - -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, SpvOptions* options) -{ - TIntermNode* root = intermediate.getTreeRoot(); - - if (root == 0) - return; - - glslang::SpvOptions defaultOptions; - if (options == nullptr) - options = &defaultOptions; - - glslang::GetThreadPoolAllocator().push(); - - TGlslangToSpvTraverser it(intermediate.getSpv().spv, &intermediate, logger, *options); - root->traverse(&it); - it.finishSpv(); - it.dumpSpv(spirv); - -#ifdef ENABLE_OPT - // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan - // eg. forward and remove memory writes of opaque types. - if ((intermediate.getSource() == EShSourceHlsl || - options->optimizeSize) && - !options->disableOptimizer) { - spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; - - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer([](spv_message_level_t level, - const char* source, - const spv_position_t& position, - const char* message) { - std::cerr << StringifyMessage(level, source, position, message) - << std::endl; - }); - - optimizer.RegisterPass(CreateInlineExhaustivePass()); - optimizer.RegisterPass(CreateEliminateDeadFunctionsPass()); - optimizer.RegisterPass(CreateScalarReplacementPass()); - optimizer.RegisterPass(CreateLocalAccessChainConvertPass()); - optimizer.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass()); - optimizer.RegisterPass(CreateLocalSingleStoreElimPass()); - optimizer.RegisterPass(CreateInsertExtractElimPass()); - optimizer.RegisterPass(CreateDeadInsertElimPass()); - optimizer.RegisterPass(CreateAggressiveDCEPass()); - optimizer.RegisterPass(CreateDeadBranchElimPass()); - optimizer.RegisterPass(CreateCFGCleanupPass()); - optimizer.RegisterPass(CreateBlockMergePass()); - optimizer.RegisterPass(CreateLocalMultiStoreElimPass()); - optimizer.RegisterPass(CreateInsertExtractElimPass()); - optimizer.RegisterPass(CreateDeadInsertElimPass()); - if (options->optimizeSize) { - optimizer.RegisterPass(CreateRedundancyEliminationPass()); - // TODO(greg-lunarg): Add this when AMD driver issues are resolved - // optimizer.RegisterPass(CreateCommonUniformElimPass()); - } - optimizer.RegisterPass(CreateAggressiveDCEPass()); - - if (!optimizer.Run(spirv.data(), spirv.size(), &spirv)) - return; - - // Remove dead module-level objects: functions, types, vars - // TODO(greg-lunarg): Switch to spirv-opt versions when available - spv::spirvbin_t Remapper(0); - Remapper.registerErrorHandler(errHandler); - Remapper.remap(spirv, spv::spirvbin_t::DCE_ALL); - } -#endif - - glslang::GetThreadPoolAllocator().pop(); -} - -}; // end namespace glslang diff --git a/third_party/glslang-spirv/GlslangToSpv.h b/third_party/glslang-spirv/GlslangToSpv.h deleted file mode 100644 index 3a4371375..000000000 --- a/third_party/glslang-spirv/GlslangToSpv.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (C) 2014 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 - -#if _MSC_VER >= 1900 - #pragma warning(disable : 4464) // relative include path contains '..' -#endif - -#include "../glslang/Include/intermediate.h" - -#include -#include - -#include "Logger.h" - -namespace glslang { - -struct SpvOptions { - SpvOptions() : generateDebugInfo(false), disableOptimizer(true), - optimizeSize(false) { } - bool generateDebugInfo; - bool disableOptimizer; - bool optimizeSize; -}; - -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/third_party/glslang-spirv/InReadableOrder.cpp b/third_party/glslang-spirv/InReadableOrder.cpp deleted file mode 100644 index 52b29613a..000000000 --- a/third_party/glslang-spirv/InReadableOrder.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// The SPIR-V spec requires code blocks to appear in an order satisfying the -// dominator-tree direction (ie, dominator before the dominated). This is, -// actually, easy to achieve: any pre-order CFG traversal algorithm will do it. -// Because such algorithms visit a block only after traversing some path to it -// from the root, they necessarily visit the block's idom first. -// -// But not every graph-traversal algorithm outputs blocks in an order that -// appears logical to human readers. The problem is that unrelated branches may -// be interspersed with each other, and merge blocks may come before some of the -// branches being merged. -// -// A good, human-readable order of blocks may be achieved by performing -// depth-first search but delaying merge nodes until after all their branches -// have been visited. This is implemented below by the inReadableOrder() -// function. - -#include "spvIR.h" - -#include -#include - -using spv::Block; -using spv::Id; - -namespace { -// Traverses CFG in a readable order, invoking a pre-set callback on each block. -// Use by calling visit() on the root block. -class ReadableOrderTraverser { -public: - explicit ReadableOrderTraverser(std::function callback) : callback_(callback) {} - // Visits the block if it hasn't been visited already and isn't currently - // being delayed. Invokes callback(block), then descends into its - // successors. Delays merge-block and continue-block processing until all - // the branches have been completed. - void visit(Block* block) - { - assert(block); - if (visited_.count(block) || delayed_.count(block)) - return; - callback_(block); - visited_.insert(block); - Block* mergeBlock = nullptr; - Block* continueBlock = nullptr; - auto mergeInst = block->getMergeInstruction(); - if (mergeInst) { - Id mergeId = mergeInst->getIdOperand(0); - mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock(); - delayed_.insert(mergeBlock); - if (mergeInst->getOpCode() == spv::OpLoopMerge) { - Id continueId = mergeInst->getIdOperand(1); - continueBlock = - block->getParent().getParent().getInstruction(continueId)->getBlock(); - delayed_.insert(continueBlock); - } - } - const auto successors = block->getSuccessors(); - for (auto it = successors.cbegin(); it != successors.cend(); ++it) - visit(*it); - if (continueBlock) { - delayed_.erase(continueBlock); - visit(continueBlock); - } - if (mergeBlock) { - delayed_.erase(mergeBlock); - visit(mergeBlock); - } - } - -private: - std::function callback_; - // Whether a block has already been visited or is being delayed. - std::unordered_set visited_, delayed_; -}; -} - -void spv::inReadableOrder(Block* root, std::function callback) -{ - ReadableOrderTraverser(callback).visit(root); -} diff --git a/third_party/glslang-spirv/Include/BaseTypes.h b/third_party/glslang-spirv/Include/BaseTypes.h deleted file mode 100644 index 050c2c4b9..000000000 --- a/third_party/glslang-spirv/Include/BaseTypes.h +++ /dev/null @@ -1,387 +0,0 @@ -// -// 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 _BASICTYPES_INCLUDED_ -#define _BASICTYPES_INCLUDED_ - -namespace glslang { - -// -// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this. -// -enum TBasicType { - EbtVoid, - EbtFloat, - EbtDouble, -#ifdef AMD_EXTENSIONS - EbtFloat16, -#endif - EbtInt, - EbtUint, - EbtInt64, - EbtUint64, -#ifdef AMD_EXTENSIONS - EbtInt16, - EbtUint16, -#endif - EbtBool, - EbtAtomicUint, - EbtSampler, - EbtStruct, - EbtBlock, - - // 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 - - // 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, - EbvSubGroupSize, - EbvSubGroupInvocation, - EbvSubGroupEqMask, - EbvSubGroupGeMask, - EbvSubGroupGtMask, - EbvSubGroupLeMask, - EbvSubGroupLtMask, - 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, - -#ifdef AMD_EXTENSIONS - EbvBaryCoordNoPersp, - EbvBaryCoordNoPerspCentroid, - EbvBaryCoordNoPerspSample, - EbvBaryCoordSmooth, - EbvBaryCoordSmoothCentroid, - EbvBaryCoordSmoothSample, - EbvBaryCoordPullModel, -#endif - - EbvViewIndex, - EbvDeviceIndex, - -#ifdef NV_EXTENSIONS - EbvViewportMaskNV, - EbvSecondaryPositionNV, - EbvSecondaryViewportMaskNV, - EbvPositionPerViewNV, - EbvViewportMaskPerViewNV, - EbvFragFullyCoveredNV, -#endif - - // 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 -}; - -// 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; - 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 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 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"; - -#ifdef AMD_EXTENSIONS - 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"; -#endif - - case EbvViewIndex: return "ViewIndex"; - case EbvDeviceIndex: return "DeviceIndex"; - -#ifdef NV_EXTENSIONS - case EbvViewportMaskNV: return "ViewportMaskNV"; - case EbvSecondaryPositionNV: return "SecondaryPositionNV"; - case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case EbvPositionPerViewNV: return "PositionPerViewNV"; - case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; -#endif - default: return "unknown built-in variable"; - } -} - -// 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 -}; - -__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"; - } -} - -} // end namespace glslang - -#endif // _BASICTYPES_INCLUDED_ diff --git a/third_party/glslang-spirv/Include/Common.h b/third_party/glslang-spirv/Include/Common.h deleted file mode 100644 index 041701774..000000000 --- a/third_party/glslang-spirv/Include/Common.h +++ /dev/null @@ -1,274 +0,0 @@ -// -// 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(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API - #include - #define snprintf sprintf_s - #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(__ANDROID__) || _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 < 1800 -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 "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) - return quoteStringName ? ("\"" + std::string(name) + "\"") : name; - return std::to_string((long long)string); - } - const char* name; // descriptive name for this string - 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/third_party/glslang-spirv/Include/ConstantUnion.h b/third_party/glslang-spirv/Include/ConstantUnion.h deleted file mode 100644 index 58c6094ea..000000000 --- a/third_party/glslang-spirv/Include/ConstantUnion.h +++ /dev/null @@ -1,625 +0,0 @@ -// -// 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 _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 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; - } - - 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 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 EbtInt64: - if (constant.i64Const == i64Const) - return true; - - break; - case EbtUint64: - if (constant.u64Const == u64Const) - return true; - - break; - case EbtDouble: - if (constant.dConst == dConst) - return true; - - break; - case EbtBool: - if (constant.bConst == bConst) - return true; - - break; - default: - assert(false && "Default missing"); - } - - return false; - } - - 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 EbtInt64: - if (i64Const > constant.i64Const) - return true; - - return false; - case EbtUint64: - if (u64Const > constant.u64Const) - return true; - - return false; - case EbtDouble: - if (dConst > constant.dConst) - return true; - - return false; - default: - assert(false && "Default missing"); - return false; - } - } - - 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 EbtInt64: - if (i64Const < constant.i64Const) - return true; - - return false; - case EbtUint64: - if (u64Const < constant.u64Const) - return true; - - return false; - case EbtDouble: - if (dConst < constant.dConst) - 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 EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break; - case EbtUint: returnValue.setUConst(uConst + constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; - case EbtDouble: returnValue.setDConst(dConst + constant.dConst); 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 EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break; - case EbtUint: returnValue.setUConst(uConst - constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; - case EbtDouble: returnValue.setDConst(dConst - constant.dConst); 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 EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break; - case EbtUint: returnValue.setUConst(uConst * constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; - case EbtDouble: returnValue.setDConst(dConst * constant.dConst); 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 EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break; - case EbtUint: returnValue.setUConst(uConst % constant.uConst); break; - case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator>>(const TConstUnion& constant) const - { - TConstUnion returnValue; - switch (type) { - case EbtInt: - switch (constant.type) { - case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; - case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; - case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; - case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; - 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; - case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; - case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt64: - switch (constant.type) { - 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 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; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator<<(const TConstUnion& constant) const - { - TConstUnion returnValue; - switch (type) { - case EbtInt: - switch (constant.type) { - case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; - case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; - case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; - case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; - 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; - case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; - case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt64: - switch (constant.type) { - 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 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; - 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 EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); 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; - case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); 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; - case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; - 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; - case EbtInt64: returnValue.setI64Const(~i64Const); break; - case EbtUint64: returnValue.setU64Const(~u64Const); 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; - } - - 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 { - 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) : unionArray(a.unionArray) { } - 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/third_party/glslang-spirv/Include/InfoSink.h b/third_party/glslang-spirv/Include/InfoSink.h deleted file mode 100644 index dceb603cf..000000000 --- a/third_party/glslang-spirv/Include/InfoSink.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// 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/third_party/glslang-spirv/Include/InitializeGlobals.h b/third_party/glslang-spirv/Include/InitializeGlobals.h deleted file mode 100644 index 95d0a40e9..000000000 --- a/third_party/glslang-spirv/Include/InitializeGlobals.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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/third_party/glslang-spirv/Include/PoolAlloc.h b/third_party/glslang-spirv/Include/PoolAlloc.h deleted file mode 100644 index 0e237a6a2..000000000 --- a/third_party/glslang-spirv/Include/PoolAlloc.h +++ /dev/null @@ -1,317 +0,0 @@ -// -// 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; } - - void setAllocator(TPoolAllocator* a) { allocator = *a; } - 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/third_party/glslang-spirv/Include/ResourceLimits.h b/third_party/glslang-spirv/Include/ResourceLimits.h deleted file mode 100644 index 0d07b8c84..000000000 --- a/third_party/glslang-spirv/Include/ResourceLimits.h +++ /dev/null @@ -1,140 +0,0 @@ -// -// 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; - - TLimits limits; -}; - -#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/third_party/glslang-spirv/Include/ShHandle.h b/third_party/glslang-spirv/Include/ShHandle.h deleted file mode 100644 index df07bd8ed..000000000 --- a/third_party/glslang-spirv/Include/ShHandle.h +++ /dev/null @@ -1,176 +0,0 @@ -// -// 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/third_party/glslang-spirv/Include/Types.h b/third_party/glslang-spirv/Include/Types.h deleted file mode 100644 index cc847b5e7..000000000 --- a/third_party/glslang-spirv/Include/Types.h +++ /dev/null @@ -1,1924 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 LunarG, Inc. -// 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 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() - bool external : 1; // GL_OES_EGL_image_external - 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, - 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 -}; - -class TQualifier { -public: - static const int layoutNotSet = -1; - - void clear() - { - precision = EpqNone; - invariant = false; - noContraction = false; - makeTemporary(); - declaredBuiltIn = EbvNone; - } - - // drop qualifiers that don't belong in a temporary variable - void makeTemporary() - { - semanticName = nullptr; - storage = EvqTemporary; - builtIn = EbvNone; - clearInterstage(); - clearMemory(); - specConstant = false; - clearLayout(); - } - - void clearInterstage() - { - clearInterpolation(); - patch = false; - sample = false; - } - - void clearInterpolation() - { - centroid = false; - smooth = false; - flat = false; - nopersp = false; -#ifdef AMD_EXTENSIONS - explicitInterp = false; -#endif - } - - void clearMemory() - { - coherent = false; - volatil = false; - restrict = false; - readonly = false; - writeonly = false; - } - - // Drop just the storage qualification, which perhaps should - // never be done, as it is fundamentally inconsistent, but need to - // explore what downstream consumers need. - // E.g., in a deference, it is an inconsistency between: - // A) partially dereferenced resource is still in the storage class it started in - // B) partially dereferenced resource is a new temporary object - // If A, then nothing should change, if B, then everything should change, but this is half way. - void makePartialTemporary() - { - storage = EvqTemporary; - specConstant = false; - } - - const char* semanticName; - TStorageQualifier storage : 6; - TBuiltInVariable builtIn : 8; - TBuiltInVariable declaredBuiltIn : 8; - TPrecisionQualifier precision : 3; - bool invariant : 1; // require canonical treatment for cross-shader invariance - bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects - bool centroid : 1; - bool smooth : 1; - bool flat : 1; - bool nopersp : 1; -#ifdef AMD_EXTENSIONS - bool explicitInterp : 1; -#endif - bool patch : 1; - bool sample : 1; - bool coherent : 1; - bool volatil : 1; - bool restrict : 1; - bool readonly : 1; - bool writeonly : 1; - bool specConstant : 1; // having a constant_id is not sufficient: expressions have no id, but are still specConstant - - bool isMemory() const - { - return coherent || volatil || restrict || readonly || writeonly; - } - bool isInterpolation() const - { -#ifdef AMD_EXTENSIONS - return flat || smooth || nopersp || explicitInterp; -#else - return flat || smooth || nopersp; -#endif - } - bool isAuxiliary() const - { - return centroid || patch || sample; - } - - 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; - } - } - - // 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(); - default: - return false; - } - } - - // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield - void clearLayout() // all layout - { - clearUniformLayout(); - - layoutPushConstant = false; -#ifdef NV_EXTENSIONS - layoutPassthrough = false; - layoutViewportRelative = false; - // -2048 as the default value indicating layoutSecondaryViewportRelative is not set - layoutSecondaryViewportRelativeOffset = -2048; -#endif - - clearInterstageLayout(); - - layoutSpecConstantId = layoutSpecConstantIdEnd; - - layoutFormat = ElfNone; - } - void clearInterstageLayout() - { - layoutLocation = layoutLocationEnd; - layoutComponent = layoutComponentEnd; - layoutIndex = layoutIndexEnd; - clearStreamLayout(); - clearXfbLayout(); - } - void clearStreamLayout() - { - layoutStream = layoutStreamEnd; - } - void clearXfbLayout() - { - layoutXfbBuffer = layoutXfbBufferEnd; - layoutXfbStride = layoutXfbStrideEnd; - layoutXfbOffset = layoutXfbOffsetEnd; - } - - bool hasNonXfbLayout() const - { - return hasUniformLayout() || - hasAnyLocation() || - hasStream() || - hasFormat() || - layoutPushConstant; - } - 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 : 10; - static const unsigned int layoutXfbStrideEnd = 0x3FF; - - unsigned int layoutXfbOffset : 10; - static const unsigned int layoutXfbOffsetEnd = 0x3FF; - - unsigned int layoutAttachment : 8; // for input_attachment_index - static const unsigned int layoutAttachmentEnd = 0XFF; - - unsigned int layoutSpecConstantId : 11; - static const unsigned int layoutSpecConstantIdEnd = 0x7FF; - - TLayoutFormat layoutFormat : 8; - - bool layoutPushConstant; - -#ifdef NV_EXTENSIONS - bool layoutPassthrough; - bool layoutViewportRelative; - int layoutSecondaryViewportRelativeOffset; -#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; - layoutAttachment = layoutAttachmentEnd; - } - - bool hasMatrix() const - { - return layoutMatrix != ElmNone; - } - bool hasPacking() const - { - return layoutPacking != ElpNone; - } - bool hasOffset() const - { - return layoutOffset != layoutNotSet; - } - bool hasAlign() const - { - return layoutAlign != layoutNotSet; - } - bool hasAnyLocation() const - { - return hasLocation() || - hasComponent() || - hasIndex(); - } - bool hasLocation() const - { - return layoutLocation != layoutLocationEnd; - } - bool hasComponent() const - { - return layoutComponent != layoutComponentEnd; - } - bool hasIndex() const - { - return layoutIndex != layoutIndexEnd; - } - bool hasSet() const - { - return layoutSet != layoutSetEnd; - } - bool hasBinding() const - { - return layoutBinding != layoutBindingEnd; - } - 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; - } - 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 ElpPacked: return "packed"; - case ElpShared: return "shared"; - case ElpStd140: return "std140"; - case ElpStd430: return "std430"; - default: return "none"; - } - } - static const char* getLayoutMatrixString(TLayoutMatrix m) - { - switch (m) { - case ElmColumnMajor: return "column_major"; - case ElmRowMajor: return "row_major"; - default: return "none"; - } - } - 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; - } - } -}; - -// 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; // both for tessellation "vertices" and geometry "max_vertices" - TVertexSpacing spacing; - TVertexOrder order; - bool pointMode; - int localSize[3]; // compute shader - int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize - bool earlyFragmentTests; // fragment input - bool postDepthCoverage; // fragment input - TLayoutDepth layoutDepth; - bool blendEquation; // true if any blend equation was specified - int numViews; // multiview extenstions - -#ifdef NV_EXTENSIONS - bool layoutOverrideCoverage; // true if layout override_coverage set -#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; - localSizeSpecId[0] = TQualifier::layoutNotSet; - localSizeSpecId[1] = TQualifier::layoutNotSet; - localSizeSpecId[2] = TQualifier::layoutNotSet; - earlyFragmentTests = false; - postDepthCoverage = false; - layoutDepth = EldNone; - blendEquation = false; - numViews = TQualifier::layoutNotSet; -#ifdef NV_EXTENSIONS - layoutOverrideCoverage = false; -#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) { - if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) - localSizeSpecId[i] = src.localSizeSpecId[i]; - } - 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; -#ifdef NV_EXTENSIONS - if (src.layoutOverrideCoverage) - layoutOverrideCoverage = src.layoutOverrideCoverage; -#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; - TArraySizes* arraySizes; - const TType* userDef; - TSourceLoc loc; - - void initType(const TSourceLoc& l) - { - basicType = EbtVoid; - vectorSize = 1; - matrixRows = 0; - matrixCols = 0; - arraySizes = nullptr; - userDef = nullptr; - loc = l; - } - - 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), - arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(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), - arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(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), - arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr) - { - if (basicType == EbtSampler) - sampler = p.sampler; - else - sampler.clear(); - qualifier = p.qualifier; - if (p.userDef) { - structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues - typeName = NewPoolTString(p.userDef->getTypeName().c_str()); - } - } - // 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), - arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), - sampler(sampler) - { - 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; - } - } - } - // for making structures, ... - TType(TTypeList* userDef, const TString& n) : - basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), - arraySizes(nullptr), structure(userDef), fieldName(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), - qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr) - { - sampler.clear(); - typeName = NewPoolTString(n.c_str()); - } - 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 - structure = copyOf.structure; - fieldName = copyOf.fieldName; - typeName = copyOf.typeName; - } - - // 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; } - - // Merge type from parent, where a parentType is at the beginning of a declaration, - // establishing some characteristics for all subsequent names, while this type - // is on the individual names. - void mergeType(const TPublicType& parentType) - { - // arrayness is currently the only child aspect that has to be preserved - basicType = parentType.basicType; - vectorSize = parentType.vectorSize; - matrixCols = parentType.matrixCols; - matrixRows = parentType.matrixRows; - vector1 = false; // TPublicType is only GLSL which so far has no vec1 - qualifier = parentType.qualifier; - sampler = parentType.sampler; - if (parentType.arraySizes) - newArraySizes(*parentType.arraySizes); - if (parentType.userDef) { - structure = parentType.userDef->getWritableStruct(); - setTypeName(parentType.userDef->getTypeName()); - } - } - - virtual void hideMember() { basicType = EbtVoid; vectorSize = 1; } - virtual bool hiddenMember() const { return basicType == EbtVoid; } - - virtual void setTypeName(const TString& n) { typeName = NewPoolTString(n.c_str()); } - 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; - } - - 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(); } - virtual bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } - virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } - virtual const TArraySizes* getArraySizes() const { return arraySizes; } - virtual TArraySizes& getArraySizes() { assert(arraySizes != nullptr); return *arraySizes; } - - 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 isExplicitlySizedArray() const { return isArray() && getOuterArraySize() != UnsizedArraySize; } - virtual bool isImplicitlySizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage != EvqBuffer; } - virtual bool isRuntimeSizedArray() const { return isArray() && getOuterArraySize() == UnsizedArraySize && qualifier.storage == EvqBuffer; } - virtual bool isStruct() const { return structure != nullptr; } -#ifdef AMD_EXTENSIONS - virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } -#else - virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble; } -#endif - virtual bool isIntegerDomain() const - { - switch (basicType) { - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: -#ifdef AMD_EXTENSIONS - case EbtInt16: - case EbtUint16: -#endif - case EbtAtomicUint: - return true; - default: - break; - } - return false; - } - virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint; } - 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(); } - - // 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 structure && 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 implicitly-sized arrays, needed for triggering a copyUp(). - virtual bool containsImplicitlySizedArray() const - { - return contains([](const TType* t) { return t->isImplicitlySizedArray(); } ); - } - - 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: -#ifdef AMD_EXTENSIONS - case EbtFloat16: -#endif - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: -#ifdef AMD_EXTENSIONS - case EbtInt16: - case EbtUint16: -#endif - case EbtBool: - return true; - default: - return false; - } - }; - - return contains(nonOpaque); - } - - virtual bool containsSpecializationSize() const - { - return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); - } - - // 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 newArraySizes(const TArraySizes& s) - { - // For setting a fresh new set of array sizes, not yet worrying about sharing. - arraySizes = new TArraySizes; - *arraySizes = s; - } - void clearArraySizes() - { - arraySizes = 0; - } - void addArrayOuterSizes(const TArraySizes& s) - { - if (arraySizes == nullptr) - newArraySizes(s); - else - arraySizes->addOuterSizes(s); - } - void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); } - void setImplicitArraySize(int s) { arraySizes->setImplicitSize(s); } - - // Recursively make the implicit array size the explicit array size, through the type tree. - void adoptImplicitArraySizes() - { - if (isImplicitlySizedArray()) - changeOuterArraySize(getImplicitArraySize()); - if (isStruct()) { - for (int i = 0; i < (int)structure->size(); ++i) - (*structure)[i].type->adoptImplicitArraySizes(); - } - } - - const char* getBasicString() const - { - return TType::getBasicString(basicType); - } - - static const char* getBasicString(TBasicType t) - { - switch (t) { - case EbtVoid: return "void"; - case EbtFloat: return "float"; - case EbtDouble: return "double"; -#ifdef AMD_EXTENSIONS - case EbtFloat16: return "float16_t"; -#endif - case EbtInt: return "int"; - case EbtUint: return "uint"; - case EbtInt64: return "int64_t"; - case EbtUint64: return "uint64_t"; -#ifdef AMD_EXTENSIONS - case EbtInt16: return "int16_t"; - case EbtUint16: return "uint16_t"; -#endif - case EbtBool: return "bool"; - case EbtAtomicUint: return "atomic_uint"; - case EbtSampler: return "sampler/image"; - case EbtStruct: return "structure"; - case EbtBlock: return "block"; - default: return "unknown type"; - } - } - - 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"); - -#ifdef NV_EXTENSIONS - if (qualifier.layoutPassthrough) - appendStr(" passthrough"); - if (qualifier.layoutViewportRelative) - appendStr(" layoutViewportRelative"); - if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { - appendStr(" layoutSecondaryViewportRelativeOffset="); - appendInt(qualifier.layoutSecondaryViewportRelativeOffset); - } -#endif - - 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"); -#ifdef AMD_EXTENSIONS - if (qualifier.explicitInterp) - appendStr(" __explicitInterpAMD"); -#endif - if (qualifier.patch) - appendStr(" patch"); - if (qualifier.sample) - appendStr(" sample"); - if (qualifier.coherent) - appendStr(" coherent"); - 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"); - appendStr(" "); - appendStr(getStorageQualifierString()); - if (isArray()) { - for(int i = 0; i < (int)arraySizes->getNumDims(); ++i) { - int size = arraySizes->getDimSize(i); - if (size == 0) - appendStr(" implicitly-sized array of"); - else { - appendStr(" "); - appendInt(arraySizes->getDimSize(i)); - appendStr("-element array of"); - } - } - } - 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 (structure) { - appendStr("{"); - for (size_t i = 0; i < structure->size(); ++i) { - if (! (*structure)[i].type->hiddenMember()) { - typeString.append((*structure)[i].type->getCompleteString()); - typeString.append(" "); - typeString.append((*structure)[i].type->getFieldName()); - if (i < structure->size() - 1) - appendStr(", "); - } - } - 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); } - const TTypeList* getStruct() const { return structure; } - void setStruct(TTypeList* s) { structure = s; } - TTypeList* getWritableStruct() const { return structure; } // This should only be used when known to not be sharing with other threads - - 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 (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 (structure == nullptr || right.structure == nullptr || - 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; - } - - // 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 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 && - sameStructType(right); - } - - // 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); - } - - bool operator!=(const TType& right) const - { - return ! operator==(right); - } - -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.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. - TQualifier qualifier; - - TArraySizes* arraySizes; // nullptr unless an array; can be shared across types - TTypeList* structure; // nullptr unless this is a struct; can be shared across types - TString *fieldName; // for structure field names - TString *typeName; // for structure type name - TSampler sampler; -}; - -} // end namespace glslang - -#endif // _TYPES_INCLUDED_ diff --git a/third_party/glslang-spirv/Include/arrays.h b/third_party/glslang-spirv/Include/arrays.h deleted file mode 100644 index 1660a99f9..000000000 --- a/third_party/glslang-spirv/Include/arrays.h +++ /dev/null @@ -1,329 +0,0 @@ -// -// 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 - -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_front(const TSmallArrayVector& newDims) - { - alloc(); - sizes->insert(sizes->begin(), 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) { } - - // For breaking into two non-shared copies, independently modifiable. - TArraySizes& operator=(const TArraySizes& from) - { - implicitArraySize = from.implicitArraySize; - 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 changeOuterSize(int s) { sizes.changeFront((unsigned)s); } - int getImplicitSize() const { return (int)implicitArraySize; } - void setImplicitSize(int s) { implicitArraySize = s; } - bool isInnerImplicit() const - { - for (int d = 1; d < sizes.size(); ++d) { - if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) - return true; - } - - return false; - } - bool clearInnerImplicit() - { - 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 isImplicit() const { return getOuterSize() == UnsizedArraySize || isInnerImplicit(); } - void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); } - 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; - } - - bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; } - bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; } - -protected: - TSmallArrayVector sizes; - - TArraySizes(const TArraySizes&); - - // for tracking maximum referenced index, before an explicit size is given - // applies only to the outer-most dimension - int implicitArraySize; -}; - -} // end namespace glslang - -#endif // _ARRAYS_INCLUDED_ diff --git a/third_party/glslang-spirv/Include/intermediate.h b/third_party/glslang-spirv/Include/intermediate.h deleted file mode 100644 index 51ac45c37..000000000 --- a/third_party/glslang-spirv/Include/intermediate.h +++ /dev/null @@ -1,1486 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-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. -// - -// -// 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 _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, - - EOpConvIntToBool, - EOpConvUintToBool, - EOpConvFloatToBool, - EOpConvDoubleToBool, - EOpConvInt64ToBool, - EOpConvUint64ToBool, - EOpConvBoolToFloat, - EOpConvIntToFloat, - EOpConvUintToFloat, - EOpConvDoubleToFloat, - EOpConvInt64ToFloat, - EOpConvUint64ToFloat, - EOpConvUintToInt, - EOpConvFloatToInt, - EOpConvBoolToInt, - EOpConvDoubleToInt, - EOpConvInt64ToInt, - EOpConvUint64ToInt, - EOpConvIntToUint, - EOpConvFloatToUint, - EOpConvBoolToUint, - EOpConvDoubleToUint, - EOpConvInt64ToUint, - EOpConvUint64ToUint, - EOpConvIntToDouble, - EOpConvUintToDouble, - EOpConvFloatToDouble, - EOpConvBoolToDouble, - EOpConvInt64ToDouble, - EOpConvUint64ToDouble, - EOpConvBoolToInt64, - EOpConvIntToInt64, - EOpConvUintToInt64, - EOpConvFloatToInt64, - EOpConvDoubleToInt64, - EOpConvUint64ToInt64, - EOpConvBoolToUint64, - EOpConvIntToUint64, - EOpConvUintToUint64, - EOpConvFloatToUint64, - EOpConvDoubleToUint64, - EOpConvInt64ToUint64, -#ifdef AMD_EXTENSIONS - EOpConvBoolToFloat16, - EOpConvIntToFloat16, - EOpConvUintToFloat16, - EOpConvFloatToFloat16, - EOpConvDoubleToFloat16, - EOpConvInt64ToFloat16, - EOpConvUint64ToFloat16, - EOpConvFloat16ToBool, - EOpConvFloat16ToInt, - EOpConvFloat16ToUint, - EOpConvFloat16ToFloat, - EOpConvFloat16ToDouble, - EOpConvFloat16ToInt64, - EOpConvFloat16ToUint64, - - EOpConvBoolToInt16, - EOpConvIntToInt16, - EOpConvUintToInt16, - EOpConvFloatToInt16, - EOpConvDoubleToInt16, - EOpConvFloat16ToInt16, - EOpConvInt64ToInt16, - EOpConvUint64ToInt16, - EOpConvUint16ToInt16, - EOpConvInt16ToBool, - EOpConvInt16ToInt, - EOpConvInt16ToUint, - EOpConvInt16ToFloat, - EOpConvInt16ToDouble, - EOpConvInt16ToFloat16, - EOpConvInt16ToInt64, - EOpConvInt16ToUint64, - - EOpConvBoolToUint16, - EOpConvIntToUint16, - EOpConvUintToUint16, - EOpConvFloatToUint16, - EOpConvDoubleToUint16, - EOpConvFloat16ToUint16, - EOpConvInt64ToUint16, - EOpConvUint64ToUint16, - EOpConvInt16ToUint16, - EOpConvUint16ToBool, - EOpConvUint16ToInt, - EOpConvUint16ToUint, - EOpConvUint16ToFloat, - EOpConvUint16ToDouble, - EOpConvUint16ToFloat16, - EOpConvUint16ToInt64, - EOpConvUint16ToUint64, -#endif - - // - // 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, -#ifdef AMD_EXTENSIONS - EOpFloat16BitsToInt16, - EOpFloat16BitsToUint16, - EOpInt16BitsToFloat16, - EOpUint16BitsToFloat16, -#endif - EOpPackSnorm2x16, - EOpUnpackSnorm2x16, - EOpPackUnorm2x16, - EOpUnpackUnorm2x16, - EOpPackSnorm4x8, - EOpUnpackSnorm4x8, - EOpPackUnorm4x8, - EOpUnpackUnorm4x8, - EOpPackHalf2x16, - EOpUnpackHalf2x16, - EOpPackDouble2x32, - EOpUnpackDouble2x32, - EOpPackInt2x32, - EOpUnpackInt2x32, - EOpPackUint2x32, - EOpUnpackUint2x32, -#ifdef AMD_EXTENSIONS - EOpPackFloat2x16, - EOpUnpackFloat2x16, - EOpPackInt2x16, - EOpUnpackInt2x16, - EOpPackUint2x16, - EOpUnpackUint2x16, - EOpPackInt4x16, - EOpUnpackInt4x16, - EOpPackUint4x16, - EOpUnpackUint4x16, -#endif - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, - -#ifdef AMD_EXTENSIONS - EOpMin3, - EOpMax3, - EOpMid3, -#endif - - 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 - -#ifdef AMD_EXTENSIONS - EOpInterpolateAtVertex, -#endif - - 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, - -#ifdef AMD_EXTENSIONS - 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, -#endif - - EOpAtomicAdd, - EOpAtomicMin, - EOpAtomicMax, - EOpAtomicAnd, - EOpAtomicOr, - EOpAtomicXor, - EOpAtomicExchange, - EOpAtomicCompSwap, - - EOpAtomicCounterIncrement, // results in pre-increment value - EOpAtomicCounterDecrement, // results in post-decrement value - EOpAtomicCounter, - EOpAtomicCounterAdd, - EOpAtomicCounterSubtract, - EOpAtomicCounterMin, - EOpAtomicCounterMax, - EOpAtomicCounterAnd, - EOpAtomicCounterOr, - EOpAtomicCounterXor, - EOpAtomicCounterExchange, - EOpAtomicCounterCompSwap, - - EOpAny, - EOpAll, - - // - // Branch - // - - EOpKill, // Fragment only - EOpReturn, - EOpBreak, - EOpContinue, - EOpCase, - EOpDefault, - - // - // Constructors - // - - EOpConstructGuardStart, - EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed - EOpConstructUint, - EOpConstructInt64, - EOpConstructUint64, -#ifdef AMD_EXTENSIONS - EOpConstructInt16, - EOpConstructUint16, -#endif - EOpConstructBool, - EOpConstructFloat, - EOpConstructDouble, -#ifdef AMD_EXTENSIONS - EOpConstructFloat16, -#endif - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructDVec2, - EOpConstructDVec3, - EOpConstructDVec4, -#ifdef AMD_EXTENSIONS - EOpConstructF16Vec2, - EOpConstructF16Vec3, - EOpConstructF16Vec4, -#endif - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructI64Vec2, - EOpConstructI64Vec3, - EOpConstructI64Vec4, - EOpConstructU64Vec2, - EOpConstructU64Vec3, - EOpConstructU64Vec4, -#ifdef AMD_EXTENSIONS - EOpConstructI16Vec2, - EOpConstructI16Vec3, - EOpConstructI16Vec4, - EOpConstructU16Vec2, - EOpConstructU16Vec3, - EOpConstructU16Vec4, -#endif - EOpConstructMat2x2, - EOpConstructMat2x3, - EOpConstructMat2x4, - EOpConstructMat3x2, - EOpConstructMat3x3, - EOpConstructMat3x4, - EOpConstructMat4x2, - EOpConstructMat4x3, - EOpConstructMat4x4, - 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, -#ifdef AMD_EXTENSIONS - EOpConstructF16Mat2x2, - EOpConstructF16Mat2x3, - EOpConstructF16Mat2x4, - EOpConstructF16Mat3x2, - EOpConstructF16Mat3x3, - EOpConstructF16Mat3x4, - EOpConstructF16Mat4x2, - EOpConstructF16Mat4x3, - EOpConstructF16Mat4x4, -#endif - EOpConstructStruct, - EOpConstructTextureSampler, - EOpConstructGuardEnd, - - // - // moves - // - - EOpAssign, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign, - EOpModAssign, - EOpAndAssign, - EOpInclusiveOrAssign, - EOpExclusiveOrAssign, - EOpLeftShiftAssign, - EOpRightShiftAssign, - - // - // Array operators - // - - EOpArrayLength, // "Array" distinguishes from length(v) built-in function, but it applies to vectors and matrices as well. - - // - // Image operations - // - - EOpImageGuardBegin, - - EOpImageQuerySize, - EOpImageQuerySamples, - EOpImageLoad, - EOpImageStore, -#ifdef AMD_EXTENSIONS - EOpImageLoadLod, - EOpImageStoreLod, -#endif - EOpImageAtomicAdd, - EOpImageAtomicMin, - EOpImageAtomicMax, - EOpImageAtomicAnd, - EOpImageAtomicOr, - EOpImageAtomicXor, - EOpImageAtomicExchange, - EOpImageAtomicCompSwap, - - EOpSubpassLoad, - EOpSubpassLoadMS, - EOpSparseImageLoad, -#ifdef AMD_EXTENSIONS - EOpSparseImageLoadLod, -#endif - - 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, -#ifdef AMD_EXTENSIONS - EOpTextureGatherLod, - EOpTextureGatherLodOffset, - EOpTextureGatherLodOffsets, - EOpFragmentMaskFetch, - EOpFragmentFetch, -#endif - - EOpSparseTextureGuardBegin, - - EOpSparseTexture, - EOpSparseTextureLod, - EOpSparseTextureOffset, - EOpSparseTextureFetch, - EOpSparseTextureFetchOffset, - EOpSparseTextureLodOffset, - EOpSparseTextureGrad, - EOpSparseTextureGradOffset, - EOpSparseTextureGather, - EOpSparseTextureGatherOffset, - EOpSparseTextureGatherOffsets, - EOpSparseTexelsResident, - EOpSparseTextureClamp, - EOpSparseTextureOffsetClamp, - EOpSparseTextureGradClamp, - EOpSparseTextureGradOffsetClamp, -#ifdef AMD_EXTENSIONS - EOpSparseTextureGatherLod, - EOpSparseTextureGatherLodOffset, - EOpSparseTextureGatherLodOffsets, -#endif - - EOpSparseTextureGuardEnd, - EOpSamplingGuardEnd, - EOpTextureGuardEnd, - - // - // Integer operations - // - - EOpAddCarry, - EOpSubBorrow, - EOpUMulExtended, - EOpIMulExtended, - EOpBitfieldExtract, - EOpBitfieldInsert, - EOpBitFieldReverse, - EOpBitCount, - EOpFindLSB, - EOpFindMSB, - - // - // 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) -}; - -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(); } - 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) - { } - - 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; } - bool getUnroll() const { return unroll; } - bool getDontUnroll() const { return dontUnroll; } - - static const unsigned int dependencyInfinite = 0xFFFFFFFF; - void setLoopDependency(int d) { dependency = d; } - int getLoopDependency() const { return dependency; } - -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 -}; - -// -// 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; } -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), -#ifdef ENABLE_HLSL - flattenSubset(-1), -#endif - constSubtree(nullptr) - { name = n; } - virtual int getId() const { return id; } - 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; } -#ifdef ENABLE_HLSL - 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 -#ifdef ENABLE_HLSL - 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; -#ifdef AMD_EXTENSIONS - bool fragMask; -#endif -}; - -// -// 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; } - bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } - bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } - bool isSparseImage() const { return op == EOpSparseImageLoad; } - - 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; -#ifdef AMD_EXTENSIONS - cracked.fragMask = false; -#endif - - 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 EOpTextureClamp: - case EOpSparseTextureClamp: - cracked.lodClamp = true; - break; - case EOpTextureProj: - cracked.proj = true; - break; - case EOpTextureLod: - case EOpSparseTextureLod: - cracked.lod = true; - break; - case EOpTextureOffset: - case EOpSparseTextureOffset: - cracked.offset = true; - break; - case EOpTextureOffsetClamp: - case EOpSparseTextureOffsetClamp: - cracked.offset = true; - cracked.lodClamp = true; - break; - case EOpTextureFetch: - case EOpSparseTextureFetch: - cracked.fetch = true; - if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || sampler.dim == Esd3D) - cracked.lod = true; - break; - case EOpTextureFetchOffset: - case EOpSparseTextureFetchOffset: - cracked.fetch = true; - cracked.offset = true; - if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || 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 EOpTextureGradClamp: - case EOpSparseTextureGradClamp: - cracked.grad = true; - cracked.lodClamp = 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; - 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; -#ifdef AMD_EXTENSIONS - 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; -#endif - case EOpSubpassLoad: - case EOpSubpassLoadMS: - cracked.subpass = true; - break; - 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), - flatten(false), dontFlatten(false) {} - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : - TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), - 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 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 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/third_party/glslang-spirv/Include/revision.h b/third_party/glslang-spirv/Include/revision.h deleted file mode 100644 index 218f8b67f..000000000 --- a/third_party/glslang-spirv/Include/revision.h +++ /dev/null @@ -1,6 +0,0 @@ -// This header is generated by the make-revision script. -// For the version, it uses the latest git tag followed by the number of commits. -// For the date, it uses the current date (when then script is run). - -#define GLSLANG_REVISION "Overload400-PrecQual.2000" -#define GLSLANG_DATE "12-Apr-2017" diff --git a/third_party/glslang-spirv/Include/revision.template b/third_party/glslang-spirv/Include/revision.template deleted file mode 100644 index 4a16beeb0..000000000 --- a/third_party/glslang-spirv/Include/revision.template +++ /dev/null @@ -1,13 +0,0 @@ -// The file revision.h should be updated to the latest version, somehow, on -// check-in, if glslang has changed. -// -// revision.template is the source for revision.h when using SubWCRev as the -// method of updating revision.h. You don't have to do it this way, the -// requirement is only that revision.h gets updated. -// -// revision.h is under source control so that not all consumers of glslang -// source have to figure out how to create revision.h just to get a build -// going. However, if it is not updated, it can be a version behind. - -#define GLSLANG_REVISION "$WCREV$" -#define GLSLANG_DATE "$WCDATE$" diff --git a/third_party/glslang-spirv/Logger.cpp b/third_party/glslang-spirv/Logger.cpp deleted file mode 100644 index 48bd4e3ad..000000000 --- a/third_party/glslang-spirv/Logger.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include "Logger.h" - -#include -#include -#include - -namespace spv { - -void SpvBuildLogger::tbdFunctionality(const std::string& f) -{ - if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures)) - tbdFeatures.push_back(f); -} - -void SpvBuildLogger::missingFunctionality(const std::string& f) -{ - if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures)) - missingFeatures.push_back(f); -} - -std::string SpvBuildLogger::getAllMessages() const { - std::ostringstream messages; - for (auto it = tbdFeatures.cbegin(); it != tbdFeatures.cend(); ++it) - messages << "TBD functionality: " << *it << "\n"; - for (auto it = missingFeatures.cbegin(); it != missingFeatures.cend(); ++it) - messages << "Missing functionality: " << *it << "\n"; - for (auto it = warnings.cbegin(); it != warnings.cend(); ++it) - messages << "warning: " << *it << "\n"; - for (auto it = errors.cbegin(); it != errors.cend(); ++it) - messages << "error: " << *it << "\n"; - return messages.str(); -} - -} // end spv namespace diff --git a/third_party/glslang-spirv/Logger.h b/third_party/glslang-spirv/Logger.h deleted file mode 100644 index 2e4ddaf51..000000000 --- a/third_party/glslang-spirv/Logger.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_SPIRV_LOGGER_H -#define GLSLANG_SPIRV_LOGGER_H - -#include -#include - -namespace spv { - -// A class for holding all SPIR-V build status messages, including -// missing/TBD functionalities, warnings, and errors. -class SpvBuildLogger { -public: - SpvBuildLogger() {} - - // Registers a TBD functionality. - void tbdFunctionality(const std::string& f); - // Registers a missing functionality. - void missingFunctionality(const std::string& f); - - // Logs a warning. - void warning(const std::string& w) { warnings.push_back(w); } - // Logs an error. - void error(const std::string& e) { errors.push_back(e); } - - // Returns all messages accumulated in the order of: - // TBD functionalities, missing functionalities, warnings, errors. - std::string getAllMessages() const; - -private: - SpvBuildLogger(const SpvBuildLogger&); - - std::vector tbdFeatures; - std::vector missingFeatures; - std::vector warnings; - std::vector errors; -}; - -} // end spv namespace - -#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/third_party/glslang-spirv/SPVRemapper.cpp b/third_party/glslang-spirv/SPVRemapper.cpp deleted file mode 100644 index f14d85729..000000000 --- a/third_party/glslang-spirv/SPVRemapper.cpp +++ /dev/null @@ -1,1479 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "SPVRemapper.h" -#include "doc.h" - -#if !defined (use_cpp11) -// ... not supported before C++11 -#else // defined (use_cpp11) - -#include -#include -#include "Include/Common.h" - -namespace spv { - - // By default, just abort on error. Can be overridden via RegisterErrorHandler - spirvbin_t::errorfn_t spirvbin_t::errorHandler = [](const std::string&) { exit(5); }; - // By default, eat log messages. Can be overridden via RegisterLogHandler - spirvbin_t::logfn_t spirvbin_t::logHandler = [](const std::string&) { }; - - // This can be overridden to provide other message behavior if needed - void spirvbin_t::msg(int minVerbosity, int indent, const std::string& txt) const - { - if (verbose >= minVerbosity) - logHandler(std::string(indent, ' ') + txt); - } - - // hash opcode, with special handling for OpExtInst - std::uint32_t spirvbin_t::asOpCodeHash(unsigned word) - { - const spv::Op opCode = asOpCode(word); - - std::uint32_t offset = 0; - - switch (opCode) { - case spv::OpExtInst: - offset += asId(word + 4); break; - default: - break; - } - - return opCode * 19 + offset; // 19 = small prime - } - - spirvbin_t::range_t spirvbin_t::literalRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeFloat: // fall through... - case spv::OpTypePointer: return range_t(2, 3); - case spv::OpTypeInt: return range_t(2, 4); - // TODO: case spv::OpTypeImage: - // TODO: case spv::OpTypeSampledImage: - case spv::OpTypeSampler: return range_t(3, 8); - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypePipe: return range_t(3, 4); - case spv::OpConstant: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::typeRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - if (isConstOp(opCode)) - return range_t(1, 2); - - switch (opCode) { - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypeSampler: // ... - case spv::OpTypeArray: // ... - case spv::OpTypeRuntimeArray: // ... - case spv::OpTypePipe: return range_t(2, 3); - case spv::OpTypeStruct: // fall through - case spv::OpTypeFunction: return range_t(2, maxCount); - case spv::OpTypePointer: return range_t(3, 4); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::constRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeArray: // fall through... - case spv::OpTypeRuntimeArray: return range_t(3, 4); - case spv::OpConstantComposite: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - // Return the size of a type in 32-bit words. This currently only - // handles ints and floats, and is only invoked by queries which must be - // integer types. If ever needed, it can be generalized. - unsigned spirvbin_t::typeSizeInWords(spv::Id id) const - { - const unsigned typeStart = idPos(id); - const spv::Op opCode = asOpCode(typeStart); - - if (errorLatch) - return 0; - - switch (opCode) { - case spv::OpTypeInt: // fall through... - case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32; - default: - return 0; - } - } - - // Looks up the type of a given const or variable ID, and - // returns its size in 32-bit words. - unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const - { - const auto tid_it = idTypeSizeMap.find(id); - if (tid_it == idTypeSizeMap.end()) { - error("type size for ID not found"); - return 0; - } - - return tid_it->second; - } - - // Is this an opcode we should remove when using --strip? - bool spirvbin_t::isStripOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpSource: - case spv::OpSourceExtension: - case spv::OpName: - case spv::OpMemberName: - case spv::OpLine: return true; - default: return false; - } - } - - // Return true if this opcode is flow control - bool spirvbin_t::isFlowCtrl(spv::Op opCode) const - { - switch (opCode) { - case spv::OpBranchConditional: - case spv::OpBranch: - case spv::OpSwitch: - case spv::OpLoopMerge: - case spv::OpSelectionMerge: - case spv::OpLabel: - case spv::OpFunction: - case spv::OpFunctionEnd: return true; - default: return false; - } - } - - // Return true if this opcode defines a type - bool spirvbin_t::isTypeOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpTypeVoid: - case spv::OpTypeBool: - case spv::OpTypeInt: - case spv::OpTypeFloat: - case spv::OpTypeVector: - case spv::OpTypeMatrix: - case spv::OpTypeImage: - case spv::OpTypeSampler: - case spv::OpTypeArray: - case spv::OpTypeRuntimeArray: - case spv::OpTypeStruct: - case spv::OpTypeOpaque: - case spv::OpTypePointer: - case spv::OpTypeFunction: - case spv::OpTypeEvent: - case spv::OpTypeDeviceEvent: - case spv::OpTypeReserveId: - case spv::OpTypeQueue: - case spv::OpTypeSampledImage: - case spv::OpTypePipe: return true; - default: return false; - } - } - - // Return true if this opcode defines a constant - bool spirvbin_t::isConstOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpConstantNull: - case spv::OpConstantSampler: - error("unimplemented constant type"); - return true; - - case spv::OpConstantTrue: - case spv::OpConstantFalse: - case spv::OpConstantComposite: - case spv::OpConstant: - return true; - - default: - return false; - } - } - - const auto inst_fn_nop = [](spv::Op, unsigned) { return false; }; - const auto op_fn_nop = [](spv::Id&) { }; - - // g++ doesn't like these defined in the class proper in an anonymous namespace. - // Dunno why. Also MSVC doesn't like the constexpr keyword. Also dunno why. - // Defining them externally seems to please both compilers, so, here they are. - const spv::Id spirvbin_t::unmapped = spv::Id(-10000); - const spv::Id spirvbin_t::unused = spv::Id(-10001); - const int spirvbin_t::header_size = 5; - - spv::Id spirvbin_t::nextUnusedId(spv::Id id) - { - while (isNewIdMapped(id)) // search for an unused ID - ++id; - - return id; - } - - spv::Id spirvbin_t::localId(spv::Id id, spv::Id newId) - { - assert(id != spv::NoResult && newId != spv::NoResult); - - if (id > bound()) { - error(std::string("ID out of range: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (id >= idMapL.size()) - idMapL.resize(id+1, unused); - - if (newId != unmapped && newId != unused) { - if (isOldIdUnused(id)) { - error(std::string("ID unused in module: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (!isOldIdUnmapped(id)) { - error(std::string("ID already mapped: ") + std::to_string(id) + " -> " - + std::to_string(localId(id))); - - return spirvbin_t::unused; - } - - if (isNewIdMapped(newId)) { - error(std::string("ID already used in module: ") + std::to_string(newId)); - return spirvbin_t::unused; - } - - msg(4, 4, std::string("map: ") + std::to_string(id) + " -> " + std::to_string(newId)); - setMapped(newId); - largestNewId = std::max(largestNewId, newId); - } - - return idMapL[id] = newId; - } - - // Parse a literal string from the SPIR binary and return it as an std::string - // Due to C++11 RValue references, this doesn't copy the result string. - std::string spirvbin_t::literalString(unsigned word) const - { - std::string literal; - - literal.reserve(16); - - const char* bytes = reinterpret_cast(spv.data() + word); - - while (bytes && *bytes) - literal += *bytes++; - - return literal; - } - - void spirvbin_t::applyMap() - { - msg(3, 2, std::string("Applying map: ")); - - // Map local IDs through the ID map - process(inst_fn_nop, // ignore instructions - [this](spv::Id& id) { - id = localId(id); - - if (errorLatch) - return; - - assert(id != unused && id != unmapped); - } - ); - } - - // Find free IDs for anything we haven't mapped - void spirvbin_t::mapRemainder() - { - msg(3, 2, std::string("Remapping remainder: ")); - - spv::Id unusedId = 1; // can't use 0: that's NoResult - spirword_t maxBound = 0; - - for (spv::Id id = 0; id < idMapL.size(); ++id) { - if (isOldIdUnused(id)) - continue; - - // Find a new mapping for any used but unmapped IDs - if (isOldIdUnmapped(id)) { - localId(id, unusedId = nextUnusedId(unusedId)); - if (errorLatch) - return; - } - - if (isOldIdUnmapped(id)) { - error(std::string("old ID not mapped: ") + std::to_string(id)); - return; - } - - // Track max bound - maxBound = std::max(maxBound, localId(id) + 1); - - if (errorLatch) - return; - } - - bound(maxBound); // reset header ID bound to as big as it now needs to be - } - - // Mark debug instructions for stripping - void spirvbin_t::stripDebug() - { - // Strip instructions in the stripOp set: debug info. - process( - [&](spv::Op opCode, unsigned start) { - // remember opcodes we want to strip later - if (isStripOp(opCode)) - stripInst(start); - return true; - }, - op_fn_nop); - } - - // Mark instructions that refer to now-removed IDs for stripping - void spirvbin_t::stripDeadRefs() - { - process( - [&](spv::Op opCode, unsigned start) { - // strip opcodes pointing to removed data - switch (opCode) { - case spv::OpName: - case spv::OpMemberName: - case spv::OpDecorate: - case spv::OpMemberDecorate: - if (idPosR.find(asId(start+1)) == idPosR.end()) - stripInst(start); - break; - default: - break; // leave it alone - } - - return true; - }, - op_fn_nop); - - strip(); - } - - // Update local maps of ID, type, etc positions - void spirvbin_t::buildLocalMaps() - { - msg(2, 2, std::string("build local maps: ")); - - mapped.clear(); - idMapL.clear(); -// preserve nameMap, so we don't clear that. - fnPos.clear(); - fnCalls.clear(); - typeConstPos.clear(); - idPosR.clear(); - entryPoint = spv::NoResult; - largestNewId = 0; - - idMapL.resize(bound(), unused); - - int fnStart = 0; - spv::Id fnRes = spv::NoResult; - - // build local Id and name maps - process( - [&](spv::Op opCode, unsigned start) { - unsigned word = start+1; - spv::Id typeId = spv::NoResult; - - if (spv::InstructionDesc[opCode].hasType()) - typeId = asId(word++); - - // If there's a result ID, remember the size of its type - if (spv::InstructionDesc[opCode].hasResult()) { - const spv::Id resultId = asId(word++); - idPosR[resultId] = start; - - if (typeId != spv::NoResult) { - const unsigned idTypeSize = typeSizeInWords(typeId); - - if (errorLatch) - return false; - - if (idTypeSize != 0) - idTypeSizeMap[resultId] = idTypeSize; - } - } - - if (opCode == spv::Op::OpName) { - const spv::Id target = asId(start+1); - const std::string name = literalString(start+2); - nameMap[name] = target; - - } else if (opCode == spv::Op::OpFunctionCall) { - ++fnCalls[asId(start + 3)]; - } else if (opCode == spv::Op::OpEntryPoint) { - entryPoint = asId(start + 2); - } else if (opCode == spv::Op::OpFunction) { - if (fnStart != 0) { - error("nested function found"); - return false; - } - - fnStart = start; - fnRes = asId(start + 2); - } else if (opCode == spv::Op::OpFunctionEnd) { - assert(fnRes != spv::NoResult); - if (fnStart == 0) { - error("function end without function start"); - return false; - } - - fnPos[fnRes] = range_t(fnStart, start + asWordCount(start)); - fnStart = 0; - } else if (isConstOp(opCode)) { - if (errorLatch) - return false; - - assert(asId(start + 2) != spv::NoResult); - typeConstPos.insert(start); - } else if (isTypeOp(opCode)) { - assert(asId(start + 1) != spv::NoResult); - typeConstPos.insert(start); - } - - return false; - }, - - [this](spv::Id& id) { localId(id, unmapped); } - ); - } - - // Validate the SPIR header - void spirvbin_t::validate() const - { - msg(2, 2, std::string("validating: ")); - - if (spv.size() < header_size) { - error("file too short: "); - return; - } - - if (magic() != spv::MagicNumber) { - error("bad magic number"); - return; - } - - // field 1 = version - // field 2 = generator magic - // field 3 = result bound - - if (schemaNum() != 0) { - error("bad schema, must be 0"); - return; - } - } - - int spirvbin_t::processInstruction(unsigned word, instfn_t instFn, idfn_t idFn) - { - const auto instructionStart = word; - const unsigned wordCount = asWordCount(instructionStart); - const int nextInst = word++ + wordCount; - spv::Op opCode = asOpCode(instructionStart); - - if (nextInst > int(spv.size())) { - error("spir instruction terminated too early"); - return -1; - } - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - if (instFn(opCode, instructionStart)) - return nextInst; - - // Read type and result ID from instruction desc table - if (spv::InstructionDesc[opCode].hasType()) { - idFn(asId(word++)); - --numOperands; - } - - if (spv::InstructionDesc[opCode].hasResult()) { - idFn(asId(word++)); - --numOperands; - } - - // Extended instructions: currently, assume everything is an ID. - // TODO: add whatever data we need for exceptions to that - if (opCode == spv::OpExtInst) { - word += 2; // instruction set, and instruction from set - numOperands -= 2; - - for (unsigned op=0; op < numOperands; ++op) - idFn(asId(word++)); // ID - - return nextInst; - } - - // Circular buffer so we can look back at previous unmapped values during the mapping pass. - static const unsigned idBufferSize = 4; - spv::Id idBuffer[idBufferSize]; - unsigned idBufferPos = 0; - - // Store IDs from instruction in our map - for (int op = 0; numOperands > 0; ++op, --numOperands) { - // SpecConstantOp is special: it includes the operands of another opcode which is - // given as a literal in the 3rd word. We will switch over to pretending that the - // opcode being processed is the literal opcode value of the SpecConstantOp. See the - // SPIRV spec for details. This way we will handle IDs and literals as appropriate for - // the embedded op. - if (opCode == spv::OpSpecConstantOp) { - if (op == 0) { - opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp. - --numOperands; - } - } - - switch (spv::InstructionDesc[opCode].operands.getClass(op)) { - case spv::OperandId: - case spv::OperandScope: - case spv::OperandMemorySemantics: - idBuffer[idBufferPos] = asId(word); - idBufferPos = (idBufferPos + 1) % idBufferSize; - idFn(asId(word++)); - break; - - case spv::OperandVariableIds: - for (unsigned i = 0; i < numOperands; ++i) - idFn(asId(word++)); - return nextInst; - - case spv::OperandVariableLiterals: - // for clarity - // if (opCode == spv::OpDecorate && asDecoration(word - 1) == spv::DecorationBuiltIn) { - // ++word; - // --numOperands; - // } - // word += numOperands; - return nextInst; - - case spv::OperandVariableLiteralId: { - if (opCode == OpSwitch) { - // word-2 is the position of the selector ID. OpSwitch Literals match its type. - // In case the IDs are currently being remapped, we get the word[-2] ID from - // the circular idBuffer. - const unsigned literalSizePos = (idBufferPos+idBufferSize-2) % idBufferSize; - const unsigned literalSize = idTypeSizeInWords(idBuffer[literalSizePos]); - const unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize); - - if (errorLatch) - return -1; - - for (unsigned arg=0; arg instPos; - instPos.reserve(unsigned(spv.size()) / 16); // initial estimate; can grow if needed. - - // Build local table of instruction start positions - process( - [&](spv::Op, unsigned start) { instPos.push_back(start); return true; }, - op_fn_nop); - - if (errorLatch) - return; - - // Window size for context-sensitive canonicalization values - // Empirical best size from a single data set. TODO: Would be a good tunable. - // We essentially perform a little convolution around each instruction, - // to capture the flavor of nearby code, to hopefully match to similar - // code in other modules. - static const unsigned windowSize = 2; - - for (unsigned entry = 0; entry < unsigned(instPos.size()); ++entry) { - const unsigned start = instPos[entry]; - const spv::Op opCode = asOpCode(start); - - if (opCode == spv::OpFunction) - fnId = asId(start + 2); - - if (opCode == spv::OpFunctionEnd) - fnId = spv::NoResult; - - if (fnId != spv::NoResult) { // if inside a function - if (spv::InstructionDesc[opCode].hasResult()) { - const unsigned word = start + (spv::InstructionDesc[opCode].hasType() ? 2 : 1); - const spv::Id resId = asId(word); - std::uint32_t hashval = fnId * 17; // small prime - - for (unsigned i = entry-1; i >= entry-windowSize; --i) { - if (asOpCode(instPos[i]) == spv::OpFunction) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - for (unsigned i = entry; i <= entry + windowSize; ++i) { - if (asOpCode(instPos[i]) == spv::OpFunctionEnd) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - - } - } - } - - spv::Op thisOpCode(spv::OpNop); - std::unordered_map opCounter; - int idCounter(0); - fnId = spv::NoResult; - - process( - [&](spv::Op opCode, unsigned start) { - switch (opCode) { - case spv::OpFunction: - // Reset counters at each function - idCounter = 0; - opCounter.clear(); - fnId = asId(start + 2); - break; - - case spv::OpImageSampleImplicitLod: - case spv::OpImageSampleExplicitLod: - case spv::OpImageSampleDrefImplicitLod: - case spv::OpImageSampleDrefExplicitLod: - case spv::OpImageSampleProjImplicitLod: - case spv::OpImageSampleProjExplicitLod: - case spv::OpImageSampleProjDrefImplicitLod: - case spv::OpImageSampleProjDrefExplicitLod: - case spv::OpDot: - case spv::OpCompositeExtract: - case spv::OpCompositeInsert: - case spv::OpVectorShuffle: - case spv::OpLabel: - case spv::OpVariable: - - case spv::OpAccessChain: - case spv::OpLoad: - case spv::OpStore: - case spv::OpCompositeConstruct: - case spv::OpFunctionCall: - ++opCounter[opCode]; - idCounter = 0; - thisOpCode = opCode; - break; - default: - thisOpCode = spv::OpNop; - } - - return false; - }, - - [&](spv::Id& id) { - if (thisOpCode != spv::OpNop) { - ++idCounter; - const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117; - - if (isOldIdUnmapped(id)) - localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - } - }); - } - - // EXPERIMENTAL: forward IO and uniform load/stores into operands - // This produces invalid Schema-0 SPIRV - void spirvbin_t::forwardLoadStores() - { - idset_t fnLocalVars; // set of function local vars - idmap_t idMap; // Map of load result IDs to what they load - - // EXPERIMENTAL: Forward input and access chain loads into consumptions - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassUniform || - spv[start+3] == spv::StorageClassUniformConstant || - spv[start+3] == spv::StorageClassInput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpAccessChain && fnLocalVars.count(asId(start+3)) > 0) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - idMap[asId(start+2)] = asId(start+3); - stripInst(start); - } - - return false; - }, - - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - // EXPERIMENTAL: Implicit output stores - fnLocalVars.clear(); - idMap.clear(); - - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassOutput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - idMap[asId(start+2)] = asId(start+1); - stripInst(start); - } - - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - process( - inst_fn_nop, - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // optimize loads and stores - void spirvbin_t::optLoadStore() - { - idset_t fnLocalVars; // candidates for removal (only locals) - idmap_t idMap; // Map of load result IDs to what they load - blockmap_t blockMap; // Map of IDs to blocks they first appear in - int blockNum = 0; // block count, to avoid crossing flow control - - // Find all the function local pointers stored at most once, and not via access chains - process( - [&](spv::Op opCode, unsigned start) { - const int wordCount = asWordCount(start); - - // Count blocks, so we can avoid crossing flow control - if (isFlowCtrl(opCode)) - ++blockNum; - - // Add local variables to the map - if ((opCode == spv::OpVariable && spv[start+3] == spv::StorageClassFunction && asWordCount(start) == 4)) { - fnLocalVars.insert(asId(start+2)); - return true; - } - - // Ignore process vars referenced via access chain - if ((opCode == spv::OpAccessChain || opCode == spv::OpInBoundsAccessChain) && fnLocalVars.count(asId(start+3)) > 0) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - return true; - } - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - const spv::Id varId = asId(start+3); - - // Avoid loads before stores - if (idMap.find(varId) == idMap.end()) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 4 && (spv[start+4] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - const spv::Id varId = asId(start+1); - - if (idMap.find(varId) == idMap.end()) { - idMap[varId] = asId(start+2); - } else { - // Remove if it has more than one store to the same pointer - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 3 && (spv[start+3] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - return false; - }, - - // If local var id used anywhere else, don't eliminate - [&](spv::Id& id) { - if (fnLocalVars.count(id) > 0) { - fnLocalVars.erase(id); - idMap.erase(id); - } - } - ); - - if (errorLatch) - return; - - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) - idMap[asId(start+2)] = idMap[asId(start+3)]; - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - // Chase replacements to their origins, in case there is a chain such as: - // 2 = store 1 - // 3 = load 2 - // 4 = store 3 - // 5 = load 4 - // We want to replace uses of 5 with 1. - for (const auto& idPair : idMap) { - spv::Id id = idPair.first; - while (idMap.find(id) != idMap.end()) // Chase to end of chain - id = idMap[id]; - - idMap[idPair.first] = id; // replace with final result - } - - // Remove the load/store/variables for the ones we've discovered - process( - [&](spv::Op opCode, unsigned start) { - if ((opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) || - (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) || - (opCode == spv::OpVariable && fnLocalVars.count(asId(start+2)) > 0)) { - - stripInst(start); - return true; - } - - return false; - }, - - [&](spv::Id& id) { - if (idMap.find(id) != idMap.end()) id = idMap[id]; - } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // remove bodies of uncalled functions - void spirvbin_t::dceFuncs() - { - msg(3, 2, std::string("Removing Dead Functions: ")); - - // TODO: There are more efficient ways to do this. - bool changed = true; - - while (changed) { - changed = false; - - for (auto fn = fnPos.begin(); fn != fnPos.end(); ) { - if (fn->first == entryPoint) { // don't DCE away the entry point! - ++fn; - continue; - } - - const auto call_it = fnCalls.find(fn->first); - - if (call_it == fnCalls.end() || call_it->second == 0) { - changed = true; - stripRange.push_back(fn->second); - - // decrease counts of called functions - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::Op::OpFunctionCall) { - const auto call_it = fnCalls.find(asId(start + 3)); - if (call_it != fnCalls.end()) { - if (--call_it->second <= 0) - fnCalls.erase(call_it); - } - } - - return true; - }, - op_fn_nop, - fn->second.first, - fn->second.second); - - if (errorLatch) - return; - - fn = fnPos.erase(fn); - } else ++fn; - } - } - } - - // remove unused function variables + decorations - void spirvbin_t::dceVars() - { - msg(3, 2, std::string("DCE Vars: ")); - - std::unordered_map varUseCount; - - // Count function variable use - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpVariable) { - ++varUseCount[asId(start+2)]; - return true; - } else if (opCode == spv::OpEntryPoint) { - const int wordCount = asWordCount(start); - for (int i = 4; i < wordCount; i++) { - ++varUseCount[asId(start+i)]; - } - return true; - } else - return false; - }, - - [&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single-use function variables + associated decorations and names - process( - [&](spv::Op opCode, unsigned start) { - spv::Id id = spv::NoResult; - if (opCode == spv::OpVariable) - id = asId(start+2); - if (opCode == spv::OpDecorate || opCode == spv::OpName) - id = asId(start+1); - - if (id != spv::NoResult && varUseCount[id] == 1) - stripInst(start); - - return true; - }, - op_fn_nop); - } - - // remove unused types - void spirvbin_t::dceTypes() - { - std::vector isType(bound(), false); - - // for speed, make O(1) way to get to type query (map is log(n)) - for (const auto typeStart : typeConstPos) - isType[asTypeConstId(typeStart)] = true; - - std::unordered_map typeUseCount; - - // This is not the most efficient algorithm, but this is an offline tool, and - // it's easy to write this way. Can be improved opportunistically if needed. - bool changed = true; - while (changed) { - changed = false; - strip(); - typeUseCount.clear(); - - // Count total type usage - process(inst_fn_nop, - [&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single reference types - for (const auto typeStart : typeConstPos) { - const spv::Id typeId = asTypeConstId(typeStart); - if (typeUseCount[typeId] == 1) { - changed = true; - --typeUseCount[typeId]; - stripInst(typeStart); - } - } - - if (errorLatch) - return; - } - } - -#ifdef NOTDEF - bool spirvbin_t::matchType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const - { - // Find the local type id "lt" and global type id "gt" - const auto lt_it = typeConstPosR.find(lt); - if (lt_it == typeConstPosR.end()) - return false; - - const auto typeStart = lt_it->second; - - // Search for entry in global table - const auto gtype = globalTypes.find(gt); - if (gtype == globalTypes.end()) - return false; - - const auto& gdata = gtype->second; - - // local wordcount and opcode - const int wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - // no type match if opcodes don't match, or operand count doesn't match - if (opCode != opOpCode(gdata[0]) || wordCount != opWordCount(gdata[0])) - return false; - - const unsigned numOperands = wordCount - 2; // all types have a result - - const auto cmpIdRange = [&](range_t range) { - for (int x=range.first; xsecond; - } - - // Hash types to canonical values. This can return ID collisions (it's a bit - // inevitable): it's up to the caller to handle that gracefully. - std::uint32_t spirvbin_t::hashType(unsigned typeStart) const - { - const unsigned wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - switch (opCode) { - case spv::OpTypeVoid: return 0; - case spv::OpTypeBool: return 1; - case spv::OpTypeInt: return 3 + (spv[typeStart+3]); - case spv::OpTypeFloat: return 5; - case spv::OpTypeVector: - return 6 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeMatrix: - return 30 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeImage: - return 120 + hashType(idPos(spv[typeStart+2])) + - spv[typeStart+3] + // dimensionality - spv[typeStart+4] * 8 * 16 + // depth - spv[typeStart+5] * 4 * 16 + // arrayed - spv[typeStart+6] * 2 * 16 + // multisampled - spv[typeStart+7] * 1 * 16; // format - case spv::OpTypeSampler: - return 500; - case spv::OpTypeSampledImage: - return 502; - case spv::OpTypeArray: - return 501 + hashType(idPos(spv[typeStart+2])) * spv[typeStart+3]; - case spv::OpTypeRuntimeArray: - return 5000 + hashType(idPos(spv[typeStart+2])); - case spv::OpTypeStruct: - { - std::uint32_t hash = 10000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeOpaque: return 6000 + spv[typeStart+2]; - case spv::OpTypePointer: return 100000 + hashType(idPos(spv[typeStart+3])); - case spv::OpTypeFunction: - { - std::uint32_t hash = 200000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeEvent: return 300000; - case spv::OpTypeDeviceEvent: return 300001; - case spv::OpTypeReserveId: return 300002; - case spv::OpTypeQueue: return 300003; - case spv::OpTypePipe: return 300004; - - case spv::OpConstantNull: return 300005; - case spv::OpConstantSampler: return 300006; - - case spv::OpConstantTrue: return 300007; - case spv::OpConstantFalse: return 300008; - case spv::OpConstantComposite: - { - std::uint32_t hash = 300011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - case spv::OpConstant: - { - std::uint32_t hash = 400011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * spv[typeStart+w]; - return hash; - } - - default: - error("unknown type opcode"); - return 0; - } - } - - void spirvbin_t::mapTypeConst() - { - globaltypes_t globalTypeMap; - - msg(3, 2, std::string("Remapping Consts & Types: ")); - - static const std::uint32_t softTypeIdLimit = 3011; // small prime. TODO: get from options - static const std::uint32_t firstMappedID = 8; // offset into ID space - - for (auto& typeStart : typeConstPos) { - const spv::Id resId = asTypeConstId(typeStart); - const std::uint32_t hashval = hashType(typeStart); - - if (errorLatch) - return; - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - } - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::strip() - { - if (stripRange.empty()) // nothing to do - return; - - // Sort strip ranges in order of traversal - std::sort(stripRange.begin(), stripRange.end()); - - // Allocate a new binary big enough to hold old binary - // We'll step this iterator through the strip ranges as we go through the binary - auto strip_it = stripRange.begin(); - - int strippedPos = 0; - for (unsigned word = 0; word < unsigned(spv.size()); ++word) { - while (strip_it != stripRange.end() && word >= strip_it->second) - ++strip_it; - - if (strip_it == stripRange.end() || word < strip_it->first || word >= strip_it->second) - spv[strippedPos++] = spv[word]; - } - - spv.resize(strippedPos); - stripRange.clear(); - - buildLocalMaps(); - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::remap(std::uint32_t opts) - { - options = opts; - - // Set up opcode tables from SpvDoc - spv::Parameterize(); - - validate(); // validate header - buildLocalMaps(); // build ID maps - - msg(3, 4, std::string("ID bound: ") + std::to_string(bound())); - - if (options & STRIP) stripDebug(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - if (options & OPT_LOADSTORE) optLoadStore(); - if (errorLatch) return; - - if (options & OPT_FWD_LS) forwardLoadStores(); - if (errorLatch) return; - - if (options & DCE_FUNCS) dceFuncs(); - if (errorLatch) return; - - if (options & DCE_VARS) dceVars(); - if (errorLatch) return; - - if (options & DCE_TYPES) dceTypes(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - stripDeadRefs(); // remove references to things we DCEed - if (errorLatch) return; - - // after the last strip, we must clean any debug info referring to now-deleted data - - if (options & MAP_TYPES) mapTypeConst(); - if (errorLatch) return; - - if (options & MAP_NAMES) mapNames(); - if (errorLatch) return; - - if (options & MAP_FUNCS) mapFnBodies(); - if (errorLatch) return; - - if (options & MAP_ALL) { - mapRemainder(); // map any unmapped IDs - if (errorLatch) return; - - applyMap(); // Now remap each shader to the new IDs we've come up with - if (errorLatch) return; - } - } - - // remap from a memory image - void spirvbin_t::remap(std::vector& in_spv, std::uint32_t opts) - { - spv.swap(in_spv); - remap(opts); - spv.swap(in_spv); - } - -} // namespace SPV - -#endif // defined (use_cpp11) - diff --git a/third_party/glslang-spirv/SPVRemapper.h b/third_party/glslang-spirv/SPVRemapper.h deleted file mode 100644 index 97e3f31fa..000000000 --- a/third_party/glslang-spirv/SPVRemapper.h +++ /dev/null @@ -1,304 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef SPIRVREMAPPER_H -#define SPIRVREMAPPER_H - -#include -#include -#include -#include - -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 || _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/third_party/glslang-spirv/SpvBuilder.cpp b/third_party/glslang-spirv/SpvBuilder.cpp deleted file mode 100644 index 0afcc6433..000000000 --- a/third_party/glslang-spirv/SpvBuilder.cpp +++ /dev/null @@ -1,2676 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// 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 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Helper for making SPIR-V IR. Generally, this is documented in the header -// SpvBuilder.h. -// - -#include -#include - -#include -#include - -#include "SpvBuilder.h" - -#ifdef AMD_EXTENSIONS - #include "hex_float.h" -#endif - -#ifndef _WIN32 - #include -#endif - -namespace spv { - -Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) : - spvVersion(spvVersion), - source(SourceLanguageUnknown), - sourceVersion(0), - sourceFileStringId(NoResult), - currentLine(0), - emitOpLines(false), - addressModel(AddressingModelLogical), - memoryModel(MemoryModelGLSL450), - builderNumber(magicNumber), - buildPoint(0), - uniqueId(0), - entryPointFunction(0), - generatingOpCodeForSpecConst(false), - logger(buildLogger) -{ - clearAccessChain(); -} - -Builder::~Builder() -{ -} - -Id Builder::import(const char* name) -{ - Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); - import->addStringOperand(name); - - imports.push_back(std::unique_ptr(import)); - return import->getResultId(); -} - -// Emit an OpLine if we've been asked to emit OpLines and the line number -// has changed since the last time, and is a valid line number. -void Builder::setLine(int lineNum) -{ - if (lineNum != 0 && lineNum != currentLine) { - currentLine = lineNum; - if (emitOpLines) - addLine(sourceFileStringId, currentLine, 0); - } -} - -void Builder::addLine(Id fileName, int lineNum, int column) -{ - Instruction* line = new Instruction(OpLine); - line->addIdOperand(fileName); - line->addImmediateOperand(lineNum); - line->addImmediateOperand(column); - buildPoint->addInstruction(std::unique_ptr(line)); -} - -// For creating new groupedTypes (will return old type if the requested one was already made). -Id Builder::makeVoidType() -{ - Instruction* type; - if (groupedTypes[OpTypeVoid].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeVoid); - groupedTypes[OpTypeVoid].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeVoid].back(); - - return type->getResultId(); -} - -Id Builder::makeBoolType() -{ - Instruction* type; - if (groupedTypes[OpTypeBool].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeBool); - groupedTypes[OpTypeBool].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeBool].back(); - - return type->getResultId(); -} - -Id Builder::makeSamplerType() -{ - Instruction* type; - if (groupedTypes[OpTypeSampler].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeSampler); - groupedTypes[OpTypeSampler].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeSampler].back(); - - return type->getResultId(); -} - -Id Builder::makePointer(StorageClass storageClass, Id pointee) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)storageClass && - type->getIdOperand(1) == pointee) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypePointer); - type->addImmediateOperand(storageClass); - type->addIdOperand(pointee); - groupedTypes[OpTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeIntegerType(int width, bool hasSign) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) { - type = groupedTypes[OpTypeInt][t]; - if (type->getImmediateOperand(0) == (unsigned)width && - type->getImmediateOperand(1) == (hasSign ? 1u : 0u)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeInt); - type->addImmediateOperand(width); - type->addImmediateOperand(hasSign ? 1 : 0); - groupedTypes[OpTypeInt].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 16: - addCapability(CapabilityInt16); - break; - case 64: - addCapability(CapabilityInt64); - break; - default: - break; - } - - return type->getResultId(); -} - -Id Builder::makeFloatType(int width) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) { - type = groupedTypes[OpTypeFloat][t]; - if (type->getImmediateOperand(0) == (unsigned)width) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeFloat); - type->addImmediateOperand(width); - groupedTypes[OpTypeFloat].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 16: - addCapability(CapabilityFloat16); - break; - case 64: - addCapability(CapabilityFloat64); - break; - default: - break; - } - - return type->getResultId(); -} - -// Make a struct without checking for duplication. -// See makeStructResultType() for non-decorated structs -// needed as the result of some instructions, which does -// check for duplicates. -Id Builder::makeStructType(const std::vector& members, const char* name) -{ - // Don't look for previous one, because in the general case, - // structs can be duplicated except for decorations. - - // not found, make it - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct); - for (int op = 0; op < (int)members.size(); ++op) - type->addIdOperand(members[op]); - groupedTypes[OpTypeStruct].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - addName(type->getResultId(), name); - - return type->getResultId(); -} - -// Make a struct for the simple results of several instructions, -// checking for duplication. -Id Builder::makeStructResultType(Id type0, Id type1) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) { - type = groupedTypes[OpTypeStruct][t]; - if (type->getNumOperands() != 2) - continue; - if (type->getIdOperand(0) != type0 || - type->getIdOperand(1) != type1) - continue; - return type->getResultId(); - } - - // not found, make it - std::vector members; - members.push_back(type0); - members.push_back(type1); - - return makeStructType(members, "ResType"); -} - -Id Builder::makeVectorType(Id component, int size) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) { - type = groupedTypes[OpTypeVector][t]; - if (type->getIdOperand(0) == component && - type->getImmediateOperand(1) == (unsigned)size) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeVector); - type->addIdOperand(component); - type->addImmediateOperand(size); - groupedTypes[OpTypeVector].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeMatrixType(Id component, int cols, int rows) -{ - assert(cols <= maxMatrixSize && rows <= maxMatrixSize); - - Id column = makeVectorType(component, rows); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) { - type = groupedTypes[OpTypeMatrix][t]; - if (type->getIdOperand(0) == column && - type->getImmediateOperand(1) == (unsigned)cols) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeMatrix); - type->addIdOperand(column); - type->addImmediateOperand(cols); - groupedTypes[OpTypeMatrix].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -// TODO: performance: track arrays per stride -// If a stride is supplied (non-zero) make an array. -// If no stride (0), reuse previous array types. -// 'size' is an Id of a constant or specialization constant of the array size -Id Builder::makeArrayType(Id element, Id sizeId, int stride) -{ - Instruction* type; - if (stride == 0) { - // try to find existing type - for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) { - type = groupedTypes[OpTypeArray][t]; - if (type->getIdOperand(0) == element && - type->getIdOperand(1) == sizeId) - return type->getResultId(); - } - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeArray); - type->addIdOperand(element); - type->addIdOperand(sizeId); - groupedTypes[OpTypeArray].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeRuntimeArray(Id element) -{ - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray); - type->addIdOperand(element); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) { - type = groupedTypes[OpTypeFunction][t]; - if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1) - continue; - bool mismatch = false; - for (int p = 0; p < (int)paramTypes.size(); ++p) { - if (paramTypes[p] != type->getIdOperand(p + 1)) { - mismatch = true; - break; - } - } - if (! mismatch) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeFunction); - type->addIdOperand(returnType); - for (int p = 0; p < (int)paramTypes.size(); ++p) - type->addIdOperand(paramTypes[p]); - groupedTypes[OpTypeFunction].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format) -{ - assert(sampled == 1 || sampled == 2); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) { - type = groupedTypes[OpTypeImage][t]; - if (type->getIdOperand(0) == sampledType && - type->getImmediateOperand(1) == (unsigned int)dim && - type->getImmediateOperand(2) == ( depth ? 1u : 0u) && - type->getImmediateOperand(3) == (arrayed ? 1u : 0u) && - type->getImmediateOperand(4) == ( ms ? 1u : 0u) && - type->getImmediateOperand(5) == sampled && - type->getImmediateOperand(6) == (unsigned int)format) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeImage); - type->addIdOperand(sampledType); - type->addImmediateOperand( dim); - type->addImmediateOperand( depth ? 1 : 0); - type->addImmediateOperand(arrayed ? 1 : 0); - type->addImmediateOperand( ms ? 1 : 0); - type->addImmediateOperand(sampled); - type->addImmediateOperand((unsigned int)format); - - groupedTypes[OpTypeImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (dim) { - case DimBuffer: - if (sampled == 1) - addCapability(CapabilitySampledBuffer); - else - addCapability(CapabilityImageBuffer); - break; - case Dim1D: - if (sampled == 1) - addCapability(CapabilitySampled1D); - else - addCapability(CapabilityImage1D); - break; - case DimCube: - if (arrayed) { - if (sampled == 1) - addCapability(CapabilitySampledCubeArray); - else - addCapability(CapabilityImageCubeArray); - } - break; - case DimRect: - if (sampled == 1) - addCapability(CapabilitySampledRect); - else - addCapability(CapabilityImageRect); - break; - case DimSubpassData: - addCapability(CapabilityInputAttachment); - break; - default: - break; - } - - if (ms) { - if (sampled == 2) { - // Images used with subpass data are not storage - // images, so don't require the capability for them. - if (dim != Dim::DimSubpassData) - addCapability(CapabilityStorageImageMultisample); - if (arrayed) - addCapability(CapabilityImageMSArray); - } - } - - return type->getResultId(); -} - -Id Builder::makeSampledImageType(Id imageType) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) { - type = groupedTypes[OpTypeSampledImage][t]; - if (type->getIdOperand(0) == imageType) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage); - type->addIdOperand(imageType); - - groupedTypes[OpTypeSampledImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::getDerefTypeId(Id resultId) const -{ - Id typeId = getTypeId(resultId); - assert(isPointerType(typeId)); - - return module.getInstruction(typeId)->getImmediateOperand(1); -} - -Op Builder::getMostBasicTypeClass(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVoid: - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypeStruct: - return typeClass; - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return getMostBasicTypeClass(instr->getIdOperand(0)); - case OpTypePointer: - return getMostBasicTypeClass(instr->getIdOperand(1)); - default: - assert(0); - return OpTypeFloat; - } -} - -int Builder::getNumTypeConstituents(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - switch (instr->getOpCode()) - { - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - return 1; - case OpTypeVector: - case OpTypeMatrix: - return instr->getImmediateOperand(1); - case OpTypeArray: - { - Id lengthId = instr->getImmediateOperand(1); - return module.getInstruction(lengthId)->getImmediateOperand(0); - } - case OpTypeStruct: - return instr->getNumOperands(); - default: - assert(0); - return 1; - } -} - -// Return the lowest-level type of scalar that an homogeneous composite is made out of. -// Typically, this is just to find out if something is made out of ints or floats. -// However, it includes returning a structure, if say, it is an array of structure. -Id Builder::getScalarTypeId(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVoid: - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypeStruct: - return instr->getResultId(); - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - case OpTypePointer: - return getScalarTypeId(getContainedTypeId(typeId)); - default: - assert(0); - return NoResult; - } -} - -// Return the type of 'member' of a composite. -Id Builder::getContainedTypeId(Id typeId, int member) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return instr->getIdOperand(0); - case OpTypePointer: - return instr->getIdOperand(1); - case OpTypeStruct: - return instr->getIdOperand(member); - default: - assert(0); - return NoResult; - } -} - -// Return the immediately contained type of a given composite type. -Id Builder::getContainedTypeId(Id typeId) const -{ - return getContainedTypeId(typeId, 0); -} - -// See if a scalar constant of this type has already been created, so it -// can be reused rather than duplicated. (Required by the specification). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == value) - return constant->getResultId(); - } - - return 0; -} - -// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64'). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == v1 && - constant->getImmediateOperand(1) == v2) - return constant->getResultId(); - } - - return 0; -} - -// Return true if consuming 'opcode' means consuming a constant. -// "constant" here means after final transform to executable code, -// the value consumed will be a constant, so includes specialization. -bool Builder::isConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpUndef: - case OpConstantTrue: - case OpConstantFalse: - case OpConstant: - case OpConstantComposite: - case OpConstantSampler: - case OpConstantNull: - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantOp: - return true; - default: - return false; - } -} - -// Return true if consuming 'opcode' means consuming a specialization constant. -bool Builder::isSpecConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantOp: - return true; - default: - return false; - } -} - -Id Builder::makeBoolConstant(bool b, bool specConstant) -{ - Id typeId = makeBoolType(); - Instruction* constant; - Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = 0; - for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) { - constant = groupedConstants[OpTypeBool][i]; - if (constant->getTypeId() == typeId && constant->getOpCode() == opcode) - existing = constant->getResultId(); - } - - if (existing) - return existing; - } - - // Make it - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeBool].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFloatConstant(float f, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(32); - union { float fl; unsigned int ui; } u; - u.fl = f; - unsigned value = u.ui; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeDoubleConstant(double d, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(64); - union { double db; unsigned long long ull; } u; - u.db = d; - unsigned long long value = u.ull; - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -#ifdef AMD_EXTENSIONS -Id Builder::makeFloat16Constant(float f16, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(16); - - spvutils::HexFloat> fVal(f16); - spvutils::HexFloat> f16Val(0); - fVal.castTo(f16Val, spvutils::kRoundToZero); - - unsigned value = f16Val.value().getAsFloat().get_value(); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (!specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} -#endif - -Id Builder::findCompositeConstant(Op typeClass, const std::vector& comps) const -{ - Instruction* constant = 0; - bool found = false; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - - // same shape? - if (constant->getNumOperands() != (int)comps.size()) - continue; - - // same contents? - bool mismatch = false; - for (int op = 0; op < constant->getNumOperands(); ++op) { - if (constant->getIdOperand(op) != comps[op]) { - mismatch = true; - break; - } - } - if (! mismatch) { - found = true; - break; - } - } - - return found ? constant->getResultId() : NoResult; -} - -// Comments in header -Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite; - assert(typeId); - Op typeClass = getTypeClass(typeId); - - switch (typeClass) { - case OpTypeVector: - case OpTypeArray: - case OpTypeStruct: - case OpTypeMatrix: - break; - default: - assert(0); - return makeFloatConstant(0.0); - } - - if (! specConstant) { - Id existing = findCompositeConstant(typeClass, members); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - for (int op = 0; op < (int)members.size(); ++op) - c->addIdOperand(members[op]); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[typeClass].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name) -{ - Instruction* entryPoint = new Instruction(OpEntryPoint); - entryPoint->addImmediateOperand(model); - entryPoint->addIdOperand(function->getId()); - entryPoint->addStringOperand(name); - - entryPoints.push_back(std::unique_ptr(entryPoint)); - - return entryPoint; -} - -// Currently relying on the fact that all 'value' of interest are small non-negative values. -void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3) -{ - Instruction* instr = new Instruction(OpExecutionMode); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - if (value1 >= 0) - instr->addImmediateOperand(value1); - if (value2 >= 0) - instr->addImmediateOperand(value2); - if (value3 >= 0) - instr->addImmediateOperand(value3); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addName(Id id, const char* string) -{ - Instruction* name = new Instruction(OpName); - name->addIdOperand(id); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addMemberName(Id id, int memberNumber, const char* string) -{ - Instruction* name = new Instruction(OpMemberName); - name->addIdOperand(id); - name->addImmediateOperand(memberNumber); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addDecoration(Id id, Decoration decoration, int num) -{ - if (decoration == spv::DecorationMax) - return; - Instruction* dec = new Instruction(OpDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) -{ - Instruction* dec = new Instruction(OpMemberDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.push_back(std::unique_ptr(dec)); -} - -// Comments in header -Function* Builder::makeEntryPoint(const char* entryPoint) -{ - assert(! entryPointFunction); - - Block* entry; - std::vector params; - std::vector> decorations; - - entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry); - - return entryPointFunction; -} - -// Comments in header -Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, - const std::vector& paramTypes, const std::vector>& decorations, Block **entry) -{ - // Make the function and initial instructions in it - Id typeId = makeFunctionType(returnType, paramTypes); - Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size()); - Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module); - - // Set up the precisions - setPrecision(function->getId(), precision); - for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { - for (int d = 0; d < (int)decorations[p].size(); ++d) - addDecoration(firstParamId + p, decorations[p][d]); - } - - // CFG - if (entry) { - *entry = new Block(getUniqueId(), *function); - function->addBlock(*entry); - setBuildPoint(*entry); - } - - if (name) - addName(function->getId(), name); - - functions.push_back(std::unique_ptr(function)); - - return function; -} - -// Comments in header -void Builder::makeReturn(bool implicit, Id retVal) -{ - if (retVal) { - Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue); - inst->addIdOperand(retVal); - buildPoint->addInstruction(std::unique_ptr(inst)); - } else - buildPoint->addInstruction(std::unique_ptr(new Instruction(NoResult, NoType, OpReturn))); - - if (! implicit) - createAndSetNoPredecessorBlock("post-return"); -} - -// Comments in header -void Builder::leaveFunction() -{ - Block* block = buildPoint; - Function& function = buildPoint->getParent(); - assert(block); - - // If our function did not contain a return, add a return void now. - if (! block->isTerminated()) { - if (function.getReturnType() == makeVoidType()) - makeReturn(true); - else { - makeReturn(true, createUndefined(function.getReturnType())); - } - } -} - -// Comments in header -void Builder::makeDiscard() -{ - buildPoint->addInstruction(std::unique_ptr(new Instruction(OpKill))); - createAndSetNoPredecessorBlock("post-discard"); -} - -// Comments in header -Id Builder::createVariable(StorageClass storageClass, Id type, const char* name) -{ - Id pointerType = makePointer(storageClass, type); - Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable); - inst->addImmediateOperand(storageClass); - - switch (storageClass) { - case StorageClassFunction: - // Validation rules require the declaration in the entry block - buildPoint->getParent().addLocalVariable(std::unique_ptr(inst)); - break; - - default: - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - break; - } - - if (name) - addName(inst->getResultId(), name); - - return inst->getResultId(); -} - -// Comments in header -Id Builder::createUndefined(Id type) -{ - Instruction* inst = new Instruction(getUniqueId(), type, OpUndef); - buildPoint->addInstruction(std::unique_ptr(inst)); - return inst->getResultId(); -} - -// Comments in header -void Builder::createStore(Id rValue, Id lValue) -{ - Instruction* store = new Instruction(OpStore); - store->addIdOperand(lValue); - store->addIdOperand(rValue); - buildPoint->addInstruction(std::unique_ptr(store)); -} - -// Comments in header -Id Builder::createLoad(Id lValue) -{ - Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad); - load->addIdOperand(lValue); - buildPoint->addInstruction(std::unique_ptr(load)); - - return load->getResultId(); -} - -// Comments in header -Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector& offsets) -{ - // Figure out the final resulting type. - spv::Id typeId = getTypeId(base); - assert(isPointerType(typeId) && offsets.size() > 0); - typeId = getContainedTypeId(typeId); - for (int i = 0; i < (int)offsets.size(); ++i) { - if (isStructType(typeId)) { - assert(isConstantScalar(offsets[i])); - typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i])); - } else - typeId = getContainedTypeId(typeId, offsets[i]); - } - typeId = makePointer(storageClass, typeId); - - // Make the instruction - Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain); - chain->addIdOperand(base); - for (int i = 0; i < (int)offsets.size(); ++i) - chain->addIdOperand(offsets[i]); - buildPoint->addInstruction(std::unique_ptr(chain)); - - return chain->getResultId(); -} - -Id Builder::createArrayLength(Id base, unsigned int member) -{ - spv::Id intType = makeIntType(32); - Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength); - length->addIdOperand(base); - length->addImmediateOperand(member); - buildPoint->addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), std::vector(1, index)); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->addIdOperand(composite); - extract->addImmediateOperand(index); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector& indexes) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), indexes); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - extract->addImmediateOperand(indexes[i]); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->addIdOperand(object); - insert->addIdOperand(composite); - insert->addImmediateOperand(index); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->addIdOperand(object); - insert->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - insert->addImmediateOperand(indexes[i]); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex) -{ - Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic); - extract->addIdOperand(vector); - extract->addIdOperand(componentIndex); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic); - insert->addIdOperand(vector); - insert->addIdOperand(component); - insert->addIdOperand(componentIndex); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -// An opcode that has no operands, no result id, and no type -void Builder::createNoResultOp(Op opCode) -{ - Instruction* op = new Instruction(opCode); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operand, no result id, and no type -void Builder::createNoResultOp(Op opCode, Id operand) -{ - Instruction* op = new Instruction(opCode); - op->addIdOperand(operand); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operand, no result id, and no type -void Builder::createNoResultOp(Op opCode, const std::vector& operands) -{ - Instruction* op = new Instruction(opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics) -{ - Instruction* op = new Instruction(OpControlBarrier); - op->addImmediateOperand(makeUintConstant(execution)); - op->addImmediateOperand(makeUintConstant(memory)); - op->addImmediateOperand(makeUintConstant(semantics)); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics) -{ - Instruction* op = new Instruction(OpMemoryBarrier); - op->addImmediateOperand(makeUintConstant(executionScope)); - op->addImmediateOperand(makeUintConstant(memorySemantics)); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operands, a result id, and a type -Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(opCode, typeId, std::vector(1, operand), std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(operand); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = left; operands[1] = right; - return createSpecConstantOp(opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(left); - op->addIdOperand(right); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(3); - operands[0] = op1; - operands[1] = op2; - operands[2] = op3; - return createSpecConstantOp( - opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(op1); - op->addIdOperand(op2); - op->addIdOperand(op3); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, const std::vector& literals) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); - op->addImmediateOperand((unsigned) opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - for (auto it = literals.cbegin(); it != literals.cend(); ++it) - op->addImmediateOperand(*it); - module.mapInstruction(op); - constantsTypesGlobals.push_back(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createFunctionCall(spv::Function* function, const std::vector& args) -{ - Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); - op->addIdOperand(function->getId()); - for (int a = 0; a < (int)args.size(); ++a) - op->addIdOperand(args[a]); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Comments in header -Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels) -{ - if (channels.size() == 1) - return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); - - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = operands[1] = source; - return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision); - } - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - assert(isVector(source)); - swizzle->addIdOperand(source); - swizzle->addIdOperand(source); - for (int i = 0; i < (int)channels.size(); ++i) - swizzle->addImmediateOperand(channels[i]); - buildPoint->addInstruction(std::unique_ptr(swizzle)); - - return setPrecision(swizzle->getResultId(), precision); -} - -// Comments in header -Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels) -{ - if (channels.size() == 1 && getNumComponents(source) == 1) - return createCompositeInsert(source, target, typeId, channels.front()); - - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - - assert(isVector(target)); - swizzle->addIdOperand(target); - - assert(getNumComponents(source) == (int)channels.size()); - assert(isVector(source)); - swizzle->addIdOperand(source); - - // Set up an identity shuffle from the base value to the result value - unsigned int components[4]; - int numTargetComponents = getNumComponents(target); - for (int i = 0; i < numTargetComponents; ++i) - components[i] = i; - - // Punch in the l-value swizzle - for (int i = 0; i < (int)channels.size(); ++i) - components[channels[i]] = numTargetComponents + i; - - // finish the instruction with these components selectors - for (int i = 0; i < numTargetComponents; ++i) - swizzle->addImmediateOperand(components[i]); - buildPoint->addInstruction(std::unique_ptr(swizzle)); - - return swizzle->getResultId(); -} - -// Comments in header -void Builder::promoteScalar(Decoration precision, Id& left, Id& right) -{ - int direction = getNumComponents(right) - getNumComponents(left); - - if (direction > 0) - left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right))); - else if (direction < 0) - right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left))); - - return; -} - -// Comments in header -Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) -{ - assert(getNumComponents(scalar) == 1); - assert(getTypeId(scalar) == getScalarTypeId(vectorType)); - - int numComponents = getNumTypeComponents(vectorType); - if (numComponents == 1) - return scalar; - - Instruction* smear = nullptr; - if (generatingOpCodeForSpecConst) { - auto members = std::vector(numComponents, scalar); - // Sometime even in spec-constant-op mode, the temporary vector created by - // promoting a scalar might not be a spec constant. This should depend on - // the scalar. - // e.g.: - // const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar; - // In such cases, the temporary vector created from a_front_end_const_scalar - // is not a spec constant vector, even though the binary operation node is marked - // as 'specConstant' and we are in spec-constant-op mode. - auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar)); - smear = module.getInstruction(result_id); - } else { - smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); - for (int c = 0; c < numComponents; ++c) - smear->addIdOperand(scalar); - buildPoint->addInstruction(std::unique_ptr(smear)); - } - - return setPrecision(smear->getResultId(), precision); -} - -// Comments in header -Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args) -{ - Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst); - inst->addIdOperand(builtins); - inst->addImmediateOperand(entryPoint); - for (int arg = 0; arg < (int)args.size(); ++arg) - inst->addIdOperand(args[arg]); - - buildPoint->addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -// Accept all parameters needed to create a texture instruction. -// Create the correct instruction based on the inputs, and make the call. -Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicitLod, const TextureParameters& parameters) -{ - static const int maxTextureArgs = 10; - Id texArgs[maxTextureArgs] = {}; - - // - // Set up the fixed arguments - // - int numArgs = 0; - bool explicitLod = false; - texArgs[numArgs++] = parameters.sampler; - texArgs[numArgs++] = parameters.coords; - if (parameters.Dref != NoResult) - texArgs[numArgs++] = parameters.Dref; - if (parameters.component != NoResult) - texArgs[numArgs++] = parameters.component; - - // - // Set up the optional arguments - // - int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments - ++numArgs; // speculatively make room for the mask operand - ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand - if (parameters.bias) { - mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask); - texArgs[numArgs++] = parameters.bias; - } - if (parameters.lod) { - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs[numArgs++] = parameters.lod; - explicitLod = true; - } else if (parameters.gradX) { - mask = (ImageOperandsMask)(mask | ImageOperandsGradMask); - texArgs[numArgs++] = parameters.gradX; - texArgs[numArgs++] = parameters.gradY; - explicitLod = true; - } else if (noImplicitLod && ! fetch && ! gather) { - // have to explicitly use lod of 0 if not allowed to have them be implicit, and - // we would otherwise be about to issue an implicit instruction - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs[numArgs++] = makeFloatConstant(0.0); - explicitLod = true; - } - if (parameters.offset) { - if (isConstant(parameters.offset)) - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask); - else { - addCapability(CapabilityImageGatherExtended); - mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask); - } - texArgs[numArgs++] = parameters.offset; - } - if (parameters.offsets) { - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask); - texArgs[numArgs++] = parameters.offsets; - } - if (parameters.sample) { - mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask); - texArgs[numArgs++] = parameters.sample; - } - if (parameters.lodClamp) { - // capability if this bit is used - addCapability(CapabilityMinLod); - - mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask); - texArgs[numArgs++] = parameters.lodClamp; - } - if (mask == ImageOperandsMaskNone) - --numArgs; // undo speculative reservation for the mask argument - else - texArgs[optArgNum] = mask; - - // - // Set up the instruction - // - Op opCode = OpNop; // All paths below need to set this - if (fetch) { - if (sparse) - opCode = OpImageSparseFetch; - else - opCode = OpImageFetch; - } else if (gather) { - if (parameters.Dref) - if (sparse) - opCode = OpImageSparseDrefGather; - else - opCode = OpImageDrefGather; - else - if (sparse) - opCode = OpImageSparseGather; - else - opCode = OpImageGather; - } else if (explicitLod) { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefExplicitLod; - else - opCode = OpImageSampleProjDrefExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefExplicitLod; - else - opCode = OpImageSampleDrefExplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjExplicitLod; - else - opCode = OpImageSampleProjExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleExplicitLod; - else - opCode = OpImageSampleExplicitLod; - } - } else { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefImplicitLod; - else - opCode = OpImageSampleProjDrefImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefImplicitLod; - else - opCode = OpImageSampleDrefImplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjImplicitLod; - else - opCode = OpImageSampleProjImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleImplicitLod; - else - opCode = OpImageSampleImplicitLod; - } - } - - // See if the result type is expecting a smeared result. - // This happens when a legacy shadow*() call is made, which - // gets a vec4 back instead of a float. - Id smearedType = resultType; - if (! isScalarType(resultType)) { - switch (opCode) { - case OpImageSampleDrefImplicitLod: - case OpImageSampleDrefExplicitLod: - case OpImageSampleProjDrefImplicitLod: - case OpImageSampleProjDrefExplicitLod: - resultType = getScalarTypeId(resultType); - break; - default: - break; - } - } - - Id typeId0 = 0; - Id typeId1 = 0; - - if (sparse) { - typeId0 = resultType; - typeId1 = getDerefTypeId(parameters.texelOut); - resultType = makeStructResultType(typeId0, typeId1); - } - - // Build the SPIR-V instruction - Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode); - for (int op = 0; op < optArgNum; ++op) - textureInst->addIdOperand(texArgs[op]); - if (optArgNum < numArgs) - textureInst->addImmediateOperand(texArgs[optArgNum]); - for (int op = optArgNum + 1; op < numArgs; ++op) - textureInst->addIdOperand(texArgs[op]); - setPrecision(textureInst->getResultId(), precision); - buildPoint->addInstruction(std::unique_ptr(textureInst)); - - Id resultId = textureInst->getResultId(); - - if (sparse) { - // set capability - addCapability(CapabilitySparseResidency); - - // Decode the return type that was a special structure - createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut); - resultId = createCompositeExtract(resultId, typeId0, 0); - setPrecision(resultId, precision); - } else { - // When a smear is needed, do it, as per what was computed - // above when resultType was changed to a scalar type. - if (resultType != smearedType) - resultId = smearScalar(precision, resultId, smearedType); - } - - return resultId; -} - -// Comments in header -Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult) -{ - // All these need a capability - addCapability(CapabilityImageQuery); - - // Figure out the result type - Id resultType = 0; - switch (opCode) { - case OpImageQuerySize: - case OpImageQuerySizeLod: - { - int numComponents = 0; - switch (getTypeDimensionality(getImageType(parameters.sampler))) { - case Dim1D: - case DimBuffer: - numComponents = 1; - break; - case Dim2D: - case DimCube: - case DimRect: - case DimSubpassData: - numComponents = 2; - break; - case Dim3D: - numComponents = 3; - break; - - default: - assert(0); - break; - } - if (isArrayedImageType(getImageType(parameters.sampler))) - ++numComponents; - - Id intType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - if (numComponents == 1) - resultType = intType; - else - resultType = makeVectorType(intType, numComponents); - - break; - } - case OpImageQueryLod: - resultType = makeVectorType(makeFloatType(32), 2); - break; - case OpImageQueryLevels: - case OpImageQuerySamples: - resultType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - break; - default: - assert(0); - break; - } - - Instruction* query = new Instruction(getUniqueId(), resultType, opCode); - query->addIdOperand(parameters.sampler); - if (parameters.coords) - query->addIdOperand(parameters.coords); - if (parameters.lod) - query->addIdOperand(parameters.lod); - buildPoint->addInstruction(std::unique_ptr(query)); - - return query->getResultId(); -} - -// External comments in header. -// Operates recursively to visit the composite's hierarchy. -Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal) -{ - Id boolType = makeBoolType(); - Id valueType = getTypeId(value1); - - Id resultId = NoResult; - - int numConstituents = getNumTypeConstituents(valueType); - - // Scalars and Vectors - - if (isScalarType(valueType) || isVectorType(valueType)) { - assert(valueType == getTypeId(value2)); - // These just need a single comparison, just have - // to figure out what it is. - Op op; - switch (getMostBasicTypeClass(valueType)) { - case OpTypeFloat: - op = equal ? OpFOrdEqual : OpFOrdNotEqual; - break; - case OpTypeInt: - default: - op = equal ? OpIEqual : OpINotEqual; - break; - case OpTypeBool: - op = equal ? OpLogicalEqual : OpLogicalNotEqual; - precision = NoPrecision; - break; - } - - if (isScalarType(valueType)) { - // scalar - resultId = createBinOp(op, boolType, value1, value2); - } else { - // vector - resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2); - setPrecision(resultId, precision); - // reduce vector compares... - resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId); - } - - return setPrecision(resultId, precision); - } - - // Only structs, arrays, and matrices should be left. - // They share in common the reduction operation across their constituents. - assert(isAggregateType(valueType) || isMatrixType(valueType)); - - // Compare each pair of constituents - for (int constituent = 0; constituent < numConstituents; ++constituent) { - std::vector indexes(1, constituent); - Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent); - Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent); - Id constituent1 = createCompositeExtract(value1, constituentType1, indexes); - Id constituent2 = createCompositeExtract(value2, constituentType2, indexes); - - Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal); - - if (constituent == 0) - resultId = subResultId; - else - resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision); - } - - return resultId; -} - -// OpCompositeConstruct -Id Builder::createCompositeConstruct(Id typeId, const std::vector& constituents) -{ - assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size())); - - if (generatingOpCodeForSpecConst) { - // Sometime, even in spec-constant-op mode, the constant composite to be - // constructed may not be a specialization constant. - // e.g.: - // const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const); - // The first column vector should be a spec constant one, as a_spec_const is a spec constant. - // The second column vector should NOT be spec constant, as it does not contain any spec constants. - // To handle such cases, we check the constituents of the constant vector to determine whether this - // vector should be created as a spec constant. - return makeCompositeConstant(typeId, constituents, - std::any_of(constituents.begin(), constituents.end(), - [&](spv::Id id) { return isSpecConstant(id); })); - } - - Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct); - for (int c = 0; c < (int)constituents.size(); ++c) - op->addIdOperand(constituents[c]); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Vector or scalar constructor -Id Builder::createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id result = NoResult; - unsigned int numTargetComponents = getNumTypeComponents(resultTypeId); - unsigned int targetComponent = 0; - - // Special case: when calling a vector constructor with a single scalar - // argument, smear the scalar - if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1) - return smearScalar(precision, sources[0], resultTypeId); - - // accumulate the arguments for OpCompositeConstruct - std::vector constituents; - Id scalarTypeId = getScalarTypeId(resultTypeId); - - // lambda to store the result of visiting an argument component - const auto latchResult = [&](Id comp) { - if (numTargetComponents > 1) - constituents.push_back(comp); - else - result = comp; - ++targetComponent; - }; - - // lambda to visit a vector argument's components - const auto accumulateVectorConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumComponents(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - for (unsigned int s = 0; s < sourcesToUse; ++s) { - std::vector swiz; - swiz.push_back(s); - latchResult(createRvalueSwizzle(precision, scalarTypeId, sourceArg, swiz)); - } - }; - - // lambda to visit a matrix argument's components - const auto accumulateMatrixConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumColumns(sourceArg) * getNumRows(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - int col = 0; - int row = 0; - for (unsigned int s = 0; s < sourcesToUse; ++s) { - if (row >= getNumRows(sourceArg)) { - row = 0; - col++; - } - std::vector indexes; - indexes.push_back(col); - indexes.push_back(row); - latchResult(createCompositeExtract(sourceArg, scalarTypeId, indexes)); - row++; - } - }; - - // Go through the source arguments, each one could have either - // a single or multiple components to contribute. - for (unsigned int i = 0; i < sources.size(); ++i) { - if (isScalar(sources[i])) - latchResult(sources[i]); - else if (isVector(sources[i])) - accumulateVectorConstituents(sources[i]); - else if (isMatrix(sources[i])) - accumulateMatrixConstituents(sources[i]); - else - assert(0); - - if (targetComponent >= numTargetComponents) - break; - } - - // If the result is a vector, make it from the gathered constituents. - if (constituents.size() > 0) - result = createCompositeConstruct(resultTypeId, constituents); - - return setPrecision(result, precision); -} - -// Comments in header -Id Builder::createMatrixConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id componentTypeId = getScalarTypeId(resultTypeId); - int numCols = getTypeNumColumns(resultTypeId); - int numRows = getTypeNumRows(resultTypeId); - - Instruction* instr = module.getInstruction(componentTypeId); - Id bitCount = instr->getIdOperand(0); - - // Will use a two step process - // 1. make a compile-time 2D array of values - // 2. construct a matrix from that array - - // Step 1. - - // initialize the array to the identity matrix - Id ids[maxMatrixSize][maxMatrixSize]; - Id one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0)); - Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0)); - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 4; ++row) { - if (col == row) - ids[col][row] = one; - else - ids[col][row] = zero; - } - } - - // modify components as dictated by the arguments - if (sources.size() == 1 && isScalar(sources[0])) { - // a single scalar; resets the diagonals - for (int col = 0; col < 4; ++col) - ids[col][col] = sources[0]; - } else if (isMatrix(sources[0])) { - // constructing from another matrix; copy over the parts that exist in both the argument and constructee - Id matrix = sources[0]; - int minCols = std::min(numCols, getNumColumns(matrix)); - int minRows = std::min(numRows, getNumRows(matrix)); - for (int col = 0; col < minCols; ++col) { - std::vector indexes; - indexes.push_back(col); - for (int row = 0; row < minRows; ++row) { - indexes.push_back(row); - ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes); - indexes.pop_back(); - setPrecision(ids[col][row], precision); - } - } - } else { - // fill in the matrix in column-major order with whatever argument components are available - int row = 0; - int col = 0; - - for (int arg = 0; arg < (int)sources.size(); ++arg) { - Id argComp = sources[arg]; - for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) { - if (getNumComponents(sources[arg]) > 1) { - argComp = createCompositeExtract(sources[arg], componentTypeId, comp); - setPrecision(argComp, precision); - } - ids[col][row++] = argComp; - if (row == numRows) { - row = 0; - col++; - } - } - } - } - - // Step 2: Construct a matrix from that array. - // First make the column vectors, then make the matrix. - - // make the column vectors - Id columnTypeId = getContainedTypeId(resultTypeId); - std::vector matrixColumns; - for (int col = 0; col < numCols; ++col) { - std::vector vectorComponents; - for (int row = 0; row < numRows; ++row) - vectorComponents.push_back(ids[col][row]); - Id column = createCompositeConstruct(columnTypeId, vectorComponents); - setPrecision(column, precision); - matrixColumns.push_back(column); - } - - // make the matrix - return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); -} - -// Comments in header -Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) : - builder(gb), - condition(cond), - control(ctrl), - elseBlock(0) -{ - function = &builder.getBuildPoint()->getParent(); - - // make the blocks, but only put the then-block into the function, - // the else-block and merge-block will be added later, in order, after - // earlier code is emitted - thenBlock = new Block(builder.getUniqueId(), *function); - mergeBlock = new Block(builder.getUniqueId(), *function); - - // Save the current block, so that we can add in the flow control split when - // makeEndIf is called. - headerBlock = builder.getBuildPoint(); - - function->addBlock(thenBlock); - builder.setBuildPoint(thenBlock); -} - -// Comments in header -void Builder::If::makeBeginElse() -{ - // Close out the "then" by having it jump to the mergeBlock - builder.createBranch(mergeBlock); - - // Make the first else block and add it to the function - elseBlock = new Block(builder.getUniqueId(), *function); - function->addBlock(elseBlock); - - // Start building the else block - builder.setBuildPoint(elseBlock); -} - -// Comments in header -void Builder::If::makeEndIf() -{ - // jump to the merge block - builder.createBranch(mergeBlock); - - // Go back to the headerBlock and make the flow control split - builder.setBuildPoint(headerBlock); - builder.createSelectionMerge(mergeBlock, control); - if (elseBlock) - builder.createConditionalBranch(condition, thenBlock, elseBlock); - else - builder.createConditionalBranch(condition, thenBlock, mergeBlock); - - // add the merge block to the function - function->addBlock(mergeBlock); - builder.setBuildPoint(mergeBlock); -} - -// Comments in header -void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueIndexToSegment, int defaultSegment, - std::vector& segmentBlocks) -{ - Function& function = buildPoint->getParent(); - - // make all the blocks - for (int s = 0; s < numSegments; ++s) - segmentBlocks.push_back(new Block(getUniqueId(), function)); - - Block* mergeBlock = new Block(getUniqueId(), function); - - // make and insert the switch's selection-merge instruction - createSelectionMerge(mergeBlock, control); - - // make the switch instruction - Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch); - switchInst->addIdOperand(selector); - auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock; - switchInst->addIdOperand(defaultOrMerge->getId()); - defaultOrMerge->addPredecessor(buildPoint); - for (int i = 0; i < (int)caseValues.size(); ++i) { - switchInst->addImmediateOperand(caseValues[i]); - switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId()); - segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint); - } - buildPoint->addInstruction(std::unique_ptr(switchInst)); - - // push the merge block - switchMerges.push(mergeBlock); -} - -// Comments in header -void Builder::addSwitchBreak() -{ - // branch to the top of the merge block stack - createBranch(switchMerges.top()); - createAndSetNoPredecessorBlock("post-switch-break"); -} - -// Comments in header -void Builder::nextSwitchSegment(std::vector& segmentBlock, int nextSegment) -{ - int lastSegment = nextSegment - 1; - if (lastSegment >= 0) { - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - createBranch(segmentBlock[nextSegment]); - } - Block* block = segmentBlock[nextSegment]; - block->getParent().addBlock(block); - setBuildPoint(block); -} - -// Comments in header -void Builder::endSwitch(std::vector& /*segmentBlock*/) -{ - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - addSwitchBreak(); - - switchMerges.top()->getParent().addBlock(switchMerges.top()); - setBuildPoint(switchMerges.top()); - - switchMerges.pop(); -} - -Block& Builder::makeNewBlock() -{ - Function& function = buildPoint->getParent(); - auto block = new Block(getUniqueId(), function); - function.addBlock(block); - return *block; -} - -Builder::LoopBlocks& Builder::makeNewLoop() -{ - // This verbosity is needed to simultaneously get the same behavior - // everywhere (id's in the same order), have a syntax that works - // across lots of versions of C++, have no warnings from pedantic - // compilation modes, and leave the rest of the code alone. - Block& head = makeNewBlock(); - Block& body = makeNewBlock(); - Block& merge = makeNewBlock(); - Block& continue_target = makeNewBlock(); - LoopBlocks blocks(head, body, merge, continue_target); - loops.push(blocks); - return loops.top(); -} - -void Builder::createLoopContinue() -{ - createBranch(&loops.top().continue_target); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-continue"); -} - -void Builder::createLoopExit() -{ - createBranch(&loops.top().merge); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-break"); -} - -void Builder::closeLoop() -{ - loops.pop(); -} - -void Builder::clearAccessChain() -{ - accessChain.base = NoResult; - accessChain.indexChain.clear(); - accessChain.instr = NoResult; - accessChain.swizzle.clear(); - accessChain.component = NoResult; - accessChain.preSwizzleBaseType = NoType; - accessChain.isRValue = false; -} - -// Comments in header -void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType) -{ - // swizzles can be stacked in GLSL, but simplified to a single - // one here; the base type doesn't change - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - - // if needed, propagate the swizzle for the current access chain - if (accessChain.swizzle.size() > 0) { - std::vector oldSwizzle = accessChain.swizzle; - accessChain.swizzle.resize(0); - for (unsigned int i = 0; i < swizzle.size(); ++i) { - assert(swizzle[i] < oldSwizzle.size()); - accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]); - } - } else - accessChain.swizzle = swizzle; - - // determine if we need to track this swizzle anymore - simplifyAccessChainSwizzle(); -} - -// Comments in header -void Builder::accessChainStore(Id rvalue) -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - Id base = collapseAccessChain(); - Id source = rvalue; - - // dynamic component should be gone - assert(accessChain.component == NoResult); - - // If swizzle still exists, it is out-of-order or not full, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. - if (accessChain.swizzle.size() > 0) { - Id tempBaseId = createLoad(base); - source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); - } - - createStore(source, base); -} - -// Comments in header -Id Builder::accessChainLoad(Decoration precision, Id resultType) -{ - Id id; - - if (accessChain.isRValue) { - // transfer access chain, but try to stay in registers - transferAccessChainSwizzle(false); - if (accessChain.indexChain.size() > 0) { - Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType; - - // if all the accesses are constants, we can use OpCompositeExtract - std::vector indexes; - bool constant = true; - for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { - if (isConstantScalar(accessChain.indexChain[i])) - indexes.push_back(getConstantScalar(accessChain.indexChain[i])); - else { - constant = false; - break; - } - } - - if (constant) - id = createCompositeExtract(accessChain.base, swizzleBase, indexes); - else { - // make a new function variable for this r-value - Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable"); - - // store into it - createStore(accessChain.base, lValue); - - // move base to the new variable - accessChain.base = lValue; - accessChain.isRValue = false; - - // load through the access chain - id = createLoad(collapseAccessChain()); - } - setPrecision(id, precision); - } else - id = accessChain.base; // no precision, it was set when this was defined - } else { - transferAccessChainSwizzle(true); - // load through the access chain - id = createLoad(collapseAccessChain()); - setPrecision(id, precision); - } - - // Done, unless there are swizzles to do - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return id; - - // Do remaining swizzling - - // Do the basic swizzle - if (accessChain.swizzle.size() > 0) { - Id swizzledType = getScalarTypeId(getTypeId(id)); - if (accessChain.swizzle.size() > 1) - swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size()); - id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle); - } - - // Do the dynamic component - if (accessChain.component != NoResult) - id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision); - - return id; -} - -Id Builder::accessChainGetLValue() -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - Id lvalue = collapseAccessChain(); - - // If swizzle exists, it is out-of-order or not full, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. This does not - // go with getting a direct l-value pointer. - assert(accessChain.swizzle.size() == 0); - assert(accessChain.component == NoResult); - - return lvalue; -} - -// comment in header -Id Builder::accessChainGetInferredType() -{ - // anything to operate on? - if (accessChain.base == NoResult) - return NoType; - Id type = getTypeId(accessChain.base); - - // do initial dereference - if (! accessChain.isRValue) - type = getContainedTypeId(type); - - // dereference each index - for (auto it = accessChain.indexChain.cbegin(); it != accessChain.indexChain.cend(); ++it) { - if (isStructType(type)) - type = getContainedTypeId(type, getConstantScalar(*it)); - else - type = getContainedTypeId(type); - } - - // dereference swizzle - if (accessChain.swizzle.size() == 1) - type = getContainedTypeId(type); - else if (accessChain.swizzle.size() > 1) - type = makeVectorType(getContainedTypeId(type), (int)accessChain.swizzle.size()); - - // dereference component selection - if (accessChain.component) - type = getContainedTypeId(type); - - return type; -} - -// comment in header -void Builder::eliminateDeadDecorations() { - std::unordered_set reachable_blocks; - std::unordered_set unreachable_definitions; - // Collect IDs defined in unreachable blocks. For each function, label the - // reachable blocks first. Then for each unreachable block, collect the - // result IDs of the instructions in it. - for (std::vector::const_iterator fi = module.getFunctions().cbegin(); - fi != module.getFunctions().cend(); fi++) { - Function* f = *fi; - Block* entry = f->getEntryBlock(); - inReadableOrder(entry, [&reachable_blocks](const Block* b) { - reachable_blocks.insert(b); - }); - for (std::vector::const_iterator bi = f->getBlocks().cbegin(); - bi != f->getBlocks().cend(); bi++) { - Block* b = *bi; - if (!reachable_blocks.count(b)) { - for (std::vector >::const_iterator - ii = b->getInstructions().cbegin(); - ii != b->getInstructions().cend(); ii++) { - Instruction* i = ii->get(); - unreachable_definitions.insert(i->getResultId()); - } - } - } - } - decorations.erase(std::remove_if(decorations.begin(), decorations.end(), - [&unreachable_definitions](std::unique_ptr& I) -> bool { - Instruction* inst = I.get(); - Id decoration_id = inst->getIdOperand(0); - return unreachable_definitions.count(decoration_id) != 0; - }), - decorations.end()); -} - -void Builder::dump(std::vector& out) const -{ - // Header, before first instructions: - out.push_back(MagicNumber); - out.push_back(spvVersion); - out.push_back(builderNumber); - out.push_back(uniqueId + 1); - out.push_back(0); - - // Capabilities - for (auto it = capabilities.cbegin(); it != capabilities.cend(); ++it) { - Instruction capInst(0, 0, OpCapability); - capInst.addImmediateOperand(*it); - capInst.dump(out); - } - - for (auto it = extensions.cbegin(); it != extensions.cend(); ++it) { - Instruction extInst(0, 0, OpExtension); - extInst.addStringOperand(it->c_str()); - extInst.dump(out); - } - - dumpInstructions(out, imports); - Instruction memInst(0, 0, OpMemoryModel); - memInst.addImmediateOperand(addressModel); - memInst.addImmediateOperand(memoryModel); - memInst.dump(out); - - // Instructions saved up while building: - dumpInstructions(out, entryPoints); - dumpInstructions(out, executionModes); - - // Debug instructions - dumpInstructions(out, strings); - dumpModuleProcesses(out); - dumpSourceInstructions(out); - for (int e = 0; e < (int)sourceExtensions.size(); ++e) { - Instruction sourceExtInst(0, 0, OpSourceExtension); - sourceExtInst.addStringOperand(sourceExtensions[e]); - sourceExtInst.dump(out); - } - dumpInstructions(out, names); - dumpInstructions(out, lines); - - // Annotation instructions - dumpInstructions(out, decorations); - - dumpInstructions(out, constantsTypesGlobals); - dumpInstructions(out, externals); - - // The functions - module.dump(out); -} - -// -// Protected methods. -// - -// Turn the described access chain in 'accessChain' into an instruction(s) -// computing its address. This *cannot* include complex swizzles, which must -// be handled after this is called. -// -// Can generate code. -Id Builder::collapseAccessChain() -{ - assert(accessChain.isRValue == false); - - // did we already emit an access chain for this? - if (accessChain.instr != NoResult) - return accessChain.instr; - - // If we have a dynamic component, we can still transfer - // that into a final operand to the access chain. We need to remap the - // dynamic component through the swizzle to get a new dynamic component to - // update. - // - // This was not done in transferAccessChainSwizzle() because it might - // generate code. - remapDynamicSwizzle(); - if (accessChain.component != NoResult) { - // transfer the dynamic component to the access chain - accessChain.indexChain.push_back(accessChain.component); - accessChain.component = NoResult; - } - - // note that non-trivial swizzling is left pending - - // do we have an access chain? - if (accessChain.indexChain.size() == 0) - return accessChain.base; - - // emit the access chain - StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base)); - accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain); - - return accessChain.instr; -} - -// For a dynamic component selection of a swizzle. -// -// Turn the swizzle and dynamic component into just a dynamic component. -// -// Generates code. -void Builder::remapDynamicSwizzle() -{ - // do we have a swizzle to remap a dynamic component through? - if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) { - // build a vector of the swizzle for the component to map into - std::vector components; - for (int c = 0; c < accessChain.swizzle.size(); ++c) - components.push_back(makeUintConstant(accessChain.swizzle[c])); - Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size()); - Id map = makeCompositeConstant(mapType, components); - - // use it - accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component); - accessChain.swizzle.clear(); - } -} - -// clear out swizzle if it is redundant, that is reselecting the same components -// that would be present without the swizzle. -void Builder::simplifyAccessChainSwizzle() -{ - // If the swizzle has fewer components than the vector, it is subsetting, and must stay - // to preserve that fact. - if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size()) - return; - - // if components are out of order, it is a swizzle - for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { - if (i != accessChain.swizzle[i]) - return; - } - - // otherwise, there is no need to track this swizzle - accessChain.swizzle.clear(); - if (accessChain.component == NoResult) - accessChain.preSwizzleBaseType = NoType; -} - -// To the extent any swizzling can become part of the chain -// of accesses instead of a post operation, make it so. -// If 'dynamic' is true, include transferring the dynamic component, -// otherwise, leave it pending. -// -// Does not generate code. just updates the access chain. -void Builder::transferAccessChainSwizzle(bool dynamic) -{ - // non existent? - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return; - - // too complex? - // (this requires either a swizzle, or generating code for a dynamic component) - if (accessChain.swizzle.size() > 1) - return; - - // single component, either in the swizzle and/or dynamic component - if (accessChain.swizzle.size() == 1) { - assert(accessChain.component == NoResult); - // handle static component selection - accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front())); - accessChain.swizzle.clear(); - accessChain.preSwizzleBaseType = NoType; - } else if (dynamic && accessChain.component != NoResult) { - assert(accessChain.swizzle.size() == 0); - // handle dynamic component - accessChain.indexChain.push_back(accessChain.component); - accessChain.preSwizzleBaseType = NoType; - accessChain.component = NoResult; - } -} - -// Utility method for creating a new block and setting the insert point to -// be in it. This is useful for flow-control operations that need a "dummy" -// block proceeding them (e.g. instructions after a discard, etc). -void Builder::createAndSetNoPredecessorBlock(const char* /*name*/) -{ - Block* block = new Block(getUniqueId(), buildPoint->getParent()); - block->setUnreachable(); - buildPoint->getParent().addBlock(block); - setBuildPoint(block); - - // if (name) - // addName(block->getId(), name); -} - -// Comments in header -void Builder::createBranch(Block* block) -{ - Instruction* branch = new Instruction(OpBranch); - branch->addIdOperand(block->getId()); - buildPoint->addInstruction(std::unique_ptr(branch)); - block->addPredecessor(buildPoint); -} - -void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control) -{ - Instruction* merge = new Instruction(OpSelectionMerge); - merge->addIdOperand(mergeBlock->getId()); - merge->addImmediateOperand(control); - buildPoint->addInstruction(std::unique_ptr(merge)); -} - -void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, - unsigned int dependencyLength) -{ - Instruction* merge = new Instruction(OpLoopMerge); - merge->addIdOperand(mergeBlock->getId()); - merge->addIdOperand(continueBlock->getId()); - merge->addImmediateOperand(control); - if ((control & LoopControlDependencyLengthMask) != 0) - merge->addImmediateOperand(dependencyLength); - buildPoint->addInstruction(std::unique_ptr(merge)); -} - -void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock) -{ - Instruction* branch = new Instruction(OpBranchConditional); - branch->addIdOperand(condition); - branch->addIdOperand(thenBlock->getId()); - branch->addIdOperand(elseBlock->getId()); - buildPoint->addInstruction(std::unique_ptr(branch)); - thenBlock->addPredecessor(buildPoint); - elseBlock->addPredecessor(buildPoint); -} - -// OpSource -// [OpSourceContinued] -// ... -void Builder::dumpSourceInstructions(std::vector& out) const -{ - const int maxWordCount = 0xFFFF; - const int opSourceWordCount = 4; - const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1; - - if (source != SourceLanguageUnknown) { - // OpSource Language Version File Source - Instruction sourceInst(NoResult, NoType, OpSource); - sourceInst.addImmediateOperand(source); - sourceInst.addImmediateOperand(sourceVersion); - // File operand - if (sourceFileStringId != NoResult) { - sourceInst.addIdOperand(sourceFileStringId); - // Source operand - if (sourceText.size() > 0) { - int nextByte = 0; - std::string subString; - while ((int)sourceText.size() - nextByte > 0) { - subString = sourceText.substr(nextByte, nonNullBytesPerInstruction); - if (nextByte == 0) { - // OpSource - sourceInst.addStringOperand(subString.c_str()); - sourceInst.dump(out); - } else { - // OpSourcContinued - Instruction sourceContinuedInst(OpSourceContinued); - sourceContinuedInst.addStringOperand(subString.c_str()); - sourceContinuedInst.dump(out); - } - nextByte += nonNullBytesPerInstruction; - } - } else - sourceInst.dump(out); - } else - sourceInst.dump(out); - } -} - -void Builder::dumpInstructions(std::vector& out, const std::vector >& instructions) const -{ - for (int i = 0; i < (int)instructions.size(); ++i) { - instructions[i]->dump(out); - } -} - -void Builder::dumpModuleProcesses(std::vector& out) const -{ - for (int i = 0; i < (int)moduleProcesses.size(); ++i) { - Instruction moduleProcessed(OpModuleProcessed); - moduleProcessed.addStringOperand(moduleProcesses[i]); - moduleProcessed.dump(out); - } -} - -}; // end spv namespace diff --git a/third_party/glslang-spirv/SpvBuilder.h b/third_party/glslang-spirv/SpvBuilder.h deleted file mode 100644 index 173d10ef2..000000000 --- a/third_party/glslang-spirv/SpvBuilder.h +++ /dev/null @@ -1,641 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// 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 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 - -namespace spv { - -class Builder { -public: - Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); - virtual ~Builder(); - - static const int maxMatrixSize = 4; - - void setSource(spv::SourceLanguage lang, int version) - { - source = lang; - sourceVersion = version; - } - void setSourceFile(const std::string& file) - { - Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString); - fileString->addStringOperand(file.c_str()); - sourceFileStringId = fileString->getResultId(); - strings.push_back(std::unique_ptr(fileString)); - } - 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); } - 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; - } - - // Log the current line, and if different than the last one, - // issue a new OpLine, using the current file name. - void setLine(int line); - // 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 type); - 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); - - // 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 isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } - bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } - - bool isBoolType(Id typeId) const { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } - bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } - bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } - bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } - bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } - bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; } - bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } - bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } - bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } - bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } - bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(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 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 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); } -#ifdef AMD_EXTENSIONS - Id makeInt16Constant(short i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)((unsigned short)i), specConstant); } - Id makeUint16Constant(unsigned short u, bool specConstant = false) { return makeIntConstant(makeUintType(16), (unsigned)u, specConstant); } -#endif - Id makeFloatConstant(float f, bool specConstant = false); - Id makeDoubleConstant(double d, bool specConstant = false); -#ifdef AMD_EXTENSIONS - Id makeFloat16Constant(float f16, bool specConstant = false); -#endif - - // 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 addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); - - // 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); - - // 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); - - // Load from an Id and return it - Id createLoad(Id lValue); - - // 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 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 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 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; - }; - - // 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&); - - // 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); // return argument - - // 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&); - }; - - // 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 - }; - - // - // 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.indexChain.push_back(offset); - } - - // push new swizzle onto the end of any existing swizzle, merging into a single swizzle - void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType); - - // 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) - { - if (accessChain.swizzle.size() != 1) { - accessChain.component = component; - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - } - } - - // use accessChain and swizzle to store value - void accessChainStore(Id rvalue); - - // use accessChain and swizzle to load an r-value - Id accessChainLoad(Decoration precision, Id ResultType); - - // 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(); - - // Remove OpDecorate instructions whose operands are defined in unreachable - // blocks. - void eliminateDeadDecorations(); - 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, unsigned int dependencyLength); - void createSelectionMerge(Block* mergeBlock, unsigned int control); - - // 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) const; - Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const; - Id findCompositeConstant(Op typeClass, const std::vector& comps) const; - Id collapseAccessChain(); - void remapDynamicSwizzle(); - void transferAccessChainSwizzle(bool dynamic); - void simplifyAccessChainSwizzle(); - void createAndSetNoPredecessorBlock(const char*); - void dumpSourceInstructions(std::vector&) const; - void dumpInstructions(std::vector&, const std::vector >&) const; - void dumpModuleProcesses(std::vector&) 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; - 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 > lines; - std::vector > decorations; - std::vector > constantsTypesGlobals; - std::vector > externals; - std::vector > functions; - - // not output, internally used for quick & dirty canonical (unique) creation - std::vector groupedConstants[OpConstant]; // all types appear before OpConstant - std::vector groupedTypes[OpConstant]; - - // stack of switches - std::stack switchMerges; - - // Our loop stack. - std::stack loops; - - // The stream for outputting warnings and errors. - SpvBuildLogger* logger; -}; // end Builder class - -}; // end spv namespace - -#endif // SpvBuilder_H diff --git a/third_party/glslang-spirv/bitutils.h b/third_party/glslang-spirv/bitutils.h deleted file mode 100644 index 31288ab69..000000000 --- a/third_party/glslang-spirv/bitutils.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef LIBSPIRV_UTIL_BITUTILS_H_ -#define LIBSPIRV_UTIL_BITUTILS_H_ - -#include -#include - -namespace spvutils { - -// Performs a bitwise copy of source to the destination type Dest. -template -Dest BitwiseCast(Src source) { - Dest dest; - static_assert(sizeof(source) == sizeof(dest), - "BitwiseCast: Source and destination must have the same size"); - std::memcpy(&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/third_party/glslang-spirv/disassemble.cpp b/third_party/glslang-spirv/disassemble.cpp deleted file mode 100644 index c950a66a0..000000000 --- a/third_party/glslang-spirv/disassemble.cpp +++ /dev/null @@ -1,695 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#include -#include -#include -#include -#include -#include -#include - -#include "disassemble.h" -#include "doc.h" - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.std.450.h" -#ifdef AMD_EXTENSIONS - #include "GLSL.ext.AMD.h" -#endif -#ifdef NV_EXTENSIONS - #include "GLSL.ext.NV.h" -#endif - } -} -const char* GlslStd450DebugNames[spv::GLSLstd450Count]; - -namespace spv { - -#ifdef AMD_EXTENSIONS -static const char* GLSLextAMDGetDebugNames(const char*, unsigned); -#endif - -#ifdef NV_EXTENSIONS -static const char* GLSLextNVGetDebugNames(const char*, unsigned); -#endif - -static void Kill(std::ostream& out, const char* message) -{ - out << std::endl << "Disassembly failed: " << message << std::endl; - exit(1); -} - -// used to identify the extended instruction library imported when printing -enum ExtInstSet { - GLSL450Inst, -#ifdef AMD_EXTENSIONS - GLSLextAMDInst, -#endif -#ifdef NV_EXTENSIONS - GLSLextNVInst, -#endif - OpenCLExtInst, -}; - -// Container class for a single instance of a SPIR-V stream, with methods for disassembly. -class SpirvStream { -public: - SpirvStream(std::ostream& out, const std::vector& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { } - virtual ~SpirvStream() { } - - void validate(); - void processInstructions(); - -protected: - SpirvStream(const SpirvStream&); - SpirvStream& operator=(const SpirvStream&); - Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; } - - // Output methods - void outputIndent(); - void formatId(Id id, std::stringstream&); - void outputResultId(Id id); - void outputTypeId(Id id); - void outputId(Id id); - void outputMask(OperandClass operandClass, unsigned mask); - void disassembleImmediates(int numOperands); - void disassembleIds(int numOperands); - int disassembleString(); - void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands); - - // Data - std::ostream& out; // where to write the disassembly - const std::vector& stream; // the actual word stream - int size; // the size of the word stream - int word; // the next word of the stream to read - - // map each to the instruction that created it - Id bound; - std::vector idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter) - - std::vector idDescriptor; // the best text string known for explaining the - - // schema - unsigned int schema; - - // stack of structured-merge points - std::stack nestedControl; - Id nextNestedControl; // need a slight delay for when we are nested -}; - -void SpirvStream::validate() -{ - size = (int)stream.size(); - if (size < 4) - Kill(out, "stream is too short"); - - // Magic number - if (stream[word++] != MagicNumber) { - out << "Bad magic number"; - return; - } - - // Version - out << "// Module Version " << std::hex << stream[word++] << std::endl; - - // Generator's magic number - out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl; - - // Result bound - bound = stream[word++]; - idInstruction.resize(bound); - idDescriptor.resize(bound); - out << "// Id's are bound by " << bound << std::endl; - out << std::endl; - - // Reserved schema, must be 0 for now - schema = stream[word++]; - if (schema != 0) - Kill(out, "bad schema, must be 0"); -} - -// Loop over all the instructions, in order, processing each. -// Boiler plate for each is handled here directly, the rest is dispatched. -void SpirvStream::processInstructions() -{ - // Instructions - while (word < size) { - int instructionStart = word; - - // Instruction wordCount and opcode - unsigned int firstWord = stream[word]; - unsigned wordCount = firstWord >> WordCountShift; - Op opCode = (Op)(firstWord & OpCodeMask); - int nextInst = word + wordCount; - ++word; - - // Presence of full instruction - if (nextInst > size) - Kill(out, "stream instruction terminated too early"); - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - // Type - Id typeId = 0; - if (InstructionDesc[opCode].hasType()) { - typeId = stream[word++]; - --numOperands; - } - - // Result - Id resultId = 0; - if (InstructionDesc[opCode].hasResult()) { - resultId = stream[word++]; - --numOperands; - - // save instruction for future reference - idInstruction[resultId] = instructionStart; - } - - outputResultId(resultId); - outputTypeId(typeId); - outputIndent(); - - // Hand off the Op and all its operands - disassembleInstruction(resultId, typeId, opCode, numOperands); - if (word != nextInst) { - out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart; - word = nextInst; - } - out << std::endl; - } -} - -void SpirvStream::outputIndent() -{ - for (int i = 0; i < (int)nestedControl.size(); ++i) - out << " "; -} - -void SpirvStream::formatId(Id id, std::stringstream& idStream) -{ - if (id != 0) { - // On instructions with no IDs, this is called with "0", which does not - // have to be within ID bounds on null shaders. - if (id >= bound) - Kill(out, "Bad "); - - idStream << id; - if (idDescriptor[id].size() > 0) - idStream << "(" << idDescriptor[id] << ")"; - } -} - -void SpirvStream::outputResultId(Id id) -{ - const int width = 16; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str(); - if (id != 0) - out << ":"; - else - out << " "; - - if (nestedControl.size() && id == nestedControl.top()) - nestedControl.pop(); -} - -void SpirvStream::outputTypeId(Id id) -{ - const int width = 12; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str() << " "; -} - -void SpirvStream::outputId(Id id) -{ - if (id >= bound) - Kill(out, "Bad "); - - out << id; - if (idDescriptor[id].size() > 0) - out << "(" << idDescriptor[id] << ")"; -} - -void SpirvStream::outputMask(OperandClass operandClass, unsigned mask) -{ - if (mask == 0) - out << "None"; - else { - for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) { - if (mask & (1 << m)) - out << OperandClassParams[operandClass].getName(m) << " "; - } - } -} - -void SpirvStream::disassembleImmediates(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - out << stream[word++]; - if (i < numOperands - 1) - out << " "; - } -} - -void SpirvStream::disassembleIds(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - outputId(stream[word++]); - if (i < numOperands - 1) - out << " "; - } -} - -// return the number of operands consumed by the string -int SpirvStream::disassembleString() -{ - int startWord = word; - - out << " \""; - - const char* wordString; - bool done = false; - do { - unsigned int content = stream[word]; - wordString = (const char*)&content; - for (int charCount = 0; charCount < 4; ++charCount) { - if (*wordString == 0) { - done = true; - break; - } - out << *(wordString++); - } - ++word; - } while (! done); - - out << "\""; - - return word - startWord; -} - -void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands) -{ - // Process the opcode - - out << (OpcodeString(opCode) + 2); // leave out the "Op" - - if (opCode == OpLoopMerge || opCode == OpSelectionMerge) - nextNestedControl = stream[word]; - else if (opCode == OpBranchConditional || opCode == OpSwitch) { - if (nextNestedControl) { - nestedControl.push(nextNestedControl); - nextNestedControl = 0; - } - } else if (opCode == OpExtInstImport) { - idDescriptor[resultId] = (const char*)(&stream[word]); - } - else { - if (resultId != 0 && idDescriptor[resultId].size() == 0) { - switch (opCode) { - case OpTypeInt: - idDescriptor[resultId] = "int"; - break; - case OpTypeFloat: - idDescriptor[resultId] = "float"; - break; - case OpTypeBool: - idDescriptor[resultId] = "bool"; - break; - case OpTypeStruct: - idDescriptor[resultId] = "struct"; - break; - case OpTypePointer: - idDescriptor[resultId] = "ptr"; - break; - case OpTypeVector: - if (idDescriptor[stream[word]].size() > 0) - idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1); - idDescriptor[resultId].append("vec"); - switch (stream[word + 1]) { - case 2: idDescriptor[resultId].append("2"); break; - case 3: idDescriptor[resultId].append("3"); break; - case 4: idDescriptor[resultId].append("4"); break; - case 8: idDescriptor[resultId].append("8"); break; - case 16: idDescriptor[resultId].append("16"); break; - case 32: idDescriptor[resultId].append("32"); break; - default: break; - } - break; - default: - break; - } - } - } - - // Process the operands. Note, a new context-dependent set could be - // swapped in mid-traversal. - - // Handle images specially, so can put out helpful strings. - if (opCode == OpTypeImage) { - out << " "; - disassembleIds(1); - out << " " << DimensionString((Dim)stream[word++]); - out << (stream[word++] != 0 ? " depth" : ""); - out << (stream[word++] != 0 ? " array" : ""); - out << (stream[word++] != 0 ? " multi-sampled" : ""); - switch (stream[word++]) { - case 0: out << " runtime"; break; - case 1: out << " sampled"; break; - case 2: out << " nonsampled"; break; - } - out << " format:" << ImageFormatString((ImageFormat)stream[word++]); - - if (numOperands == 8) { - out << " " << AccessQualifierString(stream[word++]); - } - return; - } - - // Handle all the parameterized operands - for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) { - out << " "; - OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op); - switch (operandClass) { - case OperandId: - case OperandScope: - case OperandMemorySemantics: - disassembleIds(1); - --numOperands; - // Get names for printing "(XXX)" for readability, *after* this id - if (opCode == OpName) - idDescriptor[stream[word - 1]] = (const char*)(&stream[word]); - break; - case OperandVariableIds: - disassembleIds(numOperands); - return; - case OperandImageOperands: - outputMask(OperandImageOperands, stream[word++]); - --numOperands; - disassembleIds(numOperands); - return; - case OperandOptionalLiteral: - case OperandVariableLiterals: - if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) || - (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) { - out << BuiltInString(stream[word++]); - --numOperands; - ++op; - } - disassembleImmediates(numOperands); - return; - case OperandVariableIdLiteral: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " Type "; - disassembleIds(1); - out << ", member "; - disassembleImmediates(1); - numOperands -= 2; - } - return; - case OperandVariableLiteralId: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " case "; - disassembleImmediates(1); - out << ": "; - disassembleIds(1); - numOperands -= 2; - } - return; - case OperandLiteralNumber: - disassembleImmediates(1); - --numOperands; - if (opCode == OpExtInst) { - ExtInstSet extInstSet = GLSL450Inst; - const char* name = idDescriptor[stream[word - 2]].c_str(); - if (0 == memcmp("OpenCL", name, 6)) { - extInstSet = OpenCLExtInst; -#ifdef AMD_EXTENSIONS - } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 || - strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) { - extInstSet = GLSLextAMDInst; -#endif -#ifdef NV_EXTENSIONS - }else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 || - strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 || - strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 || - strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) { - extInstSet = GLSLextNVInst; -#endif - } - unsigned entrypoint = stream[word - 1]; - if (extInstSet == GLSL450Inst) { - if (entrypoint < GLSLstd450Count) { - out << "(" << GlslStd450DebugNames[entrypoint] << ")"; - } -#ifdef AMD_EXTENSIONS - } else if (extInstSet == GLSLextAMDInst) { - out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")"; -#endif -#ifdef NV_EXTENSIONS - } - else if (extInstSet == GLSLextNVInst) { - out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")"; -#endif - } - } - break; - case OperandOptionalLiteralString: - case OperandLiteralString: - numOperands -= disassembleString(); - break; - default: - assert(operandClass >= OperandSource && operandClass < OperandOpcode); - - if (OperandClassParams[operandClass].bitmask) - outputMask(operandClass, stream[word++]); - else - out << OperandClassParams[operandClass].getName(stream[word++]); - --numOperands; - - break; - } - } - - return; -} - -static void GLSLstd450GetDebugNames(const char** names) -{ - for (int i = 0; i < GLSLstd450Count; ++i) - names[i] = "Unknown"; - - names[GLSLstd450Round] = "Round"; - names[GLSLstd450RoundEven] = "RoundEven"; - names[GLSLstd450Trunc] = "Trunc"; - names[GLSLstd450FAbs] = "FAbs"; - names[GLSLstd450SAbs] = "SAbs"; - names[GLSLstd450FSign] = "FSign"; - names[GLSLstd450SSign] = "SSign"; - names[GLSLstd450Floor] = "Floor"; - names[GLSLstd450Ceil] = "Ceil"; - names[GLSLstd450Fract] = "Fract"; - names[GLSLstd450Radians] = "Radians"; - names[GLSLstd450Degrees] = "Degrees"; - names[GLSLstd450Sin] = "Sin"; - names[GLSLstd450Cos] = "Cos"; - names[GLSLstd450Tan] = "Tan"; - names[GLSLstd450Asin] = "Asin"; - names[GLSLstd450Acos] = "Acos"; - names[GLSLstd450Atan] = "Atan"; - names[GLSLstd450Sinh] = "Sinh"; - names[GLSLstd450Cosh] = "Cosh"; - names[GLSLstd450Tanh] = "Tanh"; - names[GLSLstd450Asinh] = "Asinh"; - names[GLSLstd450Acosh] = "Acosh"; - names[GLSLstd450Atanh] = "Atanh"; - names[GLSLstd450Atan2] = "Atan2"; - names[GLSLstd450Pow] = "Pow"; - names[GLSLstd450Exp] = "Exp"; - names[GLSLstd450Log] = "Log"; - names[GLSLstd450Exp2] = "Exp2"; - names[GLSLstd450Log2] = "Log2"; - names[GLSLstd450Sqrt] = "Sqrt"; - names[GLSLstd450InverseSqrt] = "InverseSqrt"; - names[GLSLstd450Determinant] = "Determinant"; - names[GLSLstd450MatrixInverse] = "MatrixInverse"; - names[GLSLstd450Modf] = "Modf"; - names[GLSLstd450ModfStruct] = "ModfStruct"; - names[GLSLstd450FMin] = "FMin"; - names[GLSLstd450SMin] = "SMin"; - names[GLSLstd450UMin] = "UMin"; - names[GLSLstd450FMax] = "FMax"; - names[GLSLstd450SMax] = "SMax"; - names[GLSLstd450UMax] = "UMax"; - names[GLSLstd450FClamp] = "FClamp"; - names[GLSLstd450SClamp] = "SClamp"; - names[GLSLstd450UClamp] = "UClamp"; - names[GLSLstd450FMix] = "FMix"; - names[GLSLstd450Step] = "Step"; - names[GLSLstd450SmoothStep] = "SmoothStep"; - names[GLSLstd450Fma] = "Fma"; - names[GLSLstd450Frexp] = "Frexp"; - names[GLSLstd450FrexpStruct] = "FrexpStruct"; - names[GLSLstd450Ldexp] = "Ldexp"; - names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8"; - names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8"; - names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16"; - names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16"; - names[GLSLstd450PackHalf2x16] = "PackHalf2x16"; - names[GLSLstd450PackDouble2x32] = "PackDouble2x32"; - names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16"; - names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16"; - names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16"; - names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8"; - names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8"; - names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32"; - names[GLSLstd450Length] = "Length"; - names[GLSLstd450Distance] = "Distance"; - names[GLSLstd450Cross] = "Cross"; - names[GLSLstd450Normalize] = "Normalize"; - names[GLSLstd450FaceForward] = "FaceForward"; - names[GLSLstd450Reflect] = "Reflect"; - names[GLSLstd450Refract] = "Refract"; - names[GLSLstd450FindILsb] = "FindILsb"; - names[GLSLstd450FindSMsb] = "FindSMsb"; - names[GLSLstd450FindUMsb] = "FindUMsb"; - names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid"; - names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample"; - names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset"; -} - -#ifdef AMD_EXTENSIONS -static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) { - switch (entrypoint) { - case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD"; - case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD"; - case WriteInvocationAMD: return "WriteInvocationAMD"; - case MbcntAMD: return "MbcntAMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) { - switch (entrypoint) { - case FMin3AMD: return "FMin3AMD"; - case UMin3AMD: return "UMin3AMD"; - case SMin3AMD: return "SMin3AMD"; - case FMax3AMD: return "FMax3AMD"; - case UMax3AMD: return "UMax3AMD"; - case SMax3AMD: return "SMax3AMD"; - case FMid3AMD: return "FMid3AMD"; - case UMid3AMD: return "UMid3AMD"; - case SMid3AMD: return "SMid3AMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) { - switch (entrypoint) { - case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD"; - default: return "Bad"; - } - } - else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) { - switch (entrypoint) { - case CubeFaceIndexAMD: return "CubeFaceIndexAMD"; - case CubeFaceCoordAMD: return "CubeFaceCoordAMD"; - case TimeAMD: return "TimeAMD"; - default: - break; - } - } - - return "Bad"; -} -#endif - - -#ifdef NV_EXTENSIONS -static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 || - strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 || - strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 || - strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 || - strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) { - switch (entrypoint) { - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - default: return "Bad"; - } - } - return "Bad"; -} -#endif - -void Disassemble(std::ostream& out, const std::vector& stream) -{ - SpirvStream SpirvStream(out, stream); - spv::Parameterize(); - GLSLstd450GetDebugNames(GlslStd450DebugNames); - SpirvStream.validate(); - SpirvStream.processInstructions(); -} - -}; // end namespace spv diff --git a/third_party/glslang-spirv/disassemble.h b/third_party/glslang-spirv/disassemble.h deleted file mode 100644 index 47cef65a5..000000000 --- a/third_party/glslang-spirv/disassemble.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#pragma once -#ifndef disassembler_H -#define disassembler_H - -#include -#include - -namespace spv { - - void Disassemble(std::ostream& out, const std::vector&); - -}; // end namespace spv - -#endif // disassembler_H diff --git a/third_party/glslang-spirv/doc.cpp b/third_party/glslang-spirv/doc.cpp deleted file mode 100644 index 809af4c1c..000000000 --- a/third_party/glslang-spirv/doc.cpp +++ /dev/null @@ -1,2894 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// 1) Programmatically fill in instruction/operand information. -// This can be used for disassembly, printing documentation, etc. -// -// 2) Print documentation from this parameterization. -// - -#include "doc.h" - -#include -#include -#include - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" -#ifdef AMD_EXTENSIONS - #include "GLSL.ext.AMD.h" -#endif -#ifdef NV_EXTENSIONS - #include "GLSL.ext.NV.h" -#endif - } -} - -namespace spv { - -// -// Whole set of functions that translate enumerants to their text strings for -// the specification (or their sanitized versions for auto-generating the -// spirv headers. -// -// Also, the ceilings are declared next to these, to help keep them in sync. -// Ceilings should be -// - one more than the maximum value an enumerant takes on, for non-mask enumerants -// (for non-sparse enums, this is the number of enumerants) -// - the number of bits consumed by the set of masks -// (for non-sparse mask enums, this is the number of enumerants) -// - -const int SourceLanguageCeiling = 6; // HLSL todo: need official enumerant - -const char* SourceString(int source) -{ - switch (source) { - case 0: return "Unknown"; - case 1: return "ESSL"; - case 2: return "GLSL"; - case 3: return "OpenCL_C"; - case 4: return "OpenCL_CPP"; - case 5: return "HLSL"; - - case SourceLanguageCeiling: - default: return "Bad"; - } -} - -const int ExecutionModelCeiling = 7; - -const char* ExecutionModelString(int model) -{ - switch (model) { - case 0: return "Vertex"; - case 1: return "TessellationControl"; - case 2: return "TessellationEvaluation"; - case 3: return "Geometry"; - case 4: return "Fragment"; - case 5: return "GLCompute"; - case 6: return "Kernel"; - - case ExecutionModelCeiling: - default: return "Bad"; - } -} - -const int AddressingModelCeiling = 3; - -const char* AddressingString(int addr) -{ - switch (addr) { - case 0: return "Logical"; - case 1: return "Physical32"; - case 2: return "Physical64"; - - case AddressingModelCeiling: - default: return "Bad"; - } -} - -const int MemoryModelCeiling = 3; - -const char* MemoryString(int mem) -{ - switch (mem) { - case 0: return "Simple"; - case 1: return "GLSL450"; - case 2: return "OpenCL"; - - case MemoryModelCeiling: - default: return "Bad"; - } -} - -const int ExecutionModeCeiling = 33; - -const char* ExecutionModeString(int mode) -{ - switch (mode) { - case 0: return "Invocations"; - case 1: return "SpacingEqual"; - case 2: return "SpacingFractionalEven"; - case 3: return "SpacingFractionalOdd"; - case 4: return "VertexOrderCw"; - case 5: return "VertexOrderCcw"; - case 6: return "PixelCenterInteger"; - case 7: return "OriginUpperLeft"; - case 8: return "OriginLowerLeft"; - case 9: return "EarlyFragmentTests"; - case 10: return "PointMode"; - case 11: return "Xfb"; - case 12: return "DepthReplacing"; - case 13: return "Bad"; - case 14: return "DepthGreater"; - case 15: return "DepthLess"; - case 16: return "DepthUnchanged"; - case 17: return "LocalSize"; - case 18: return "LocalSizeHint"; - case 19: return "InputPoints"; - case 20: return "InputLines"; - case 21: return "InputLinesAdjacency"; - case 22: return "Triangles"; - case 23: return "InputTrianglesAdjacency"; - case 24: return "Quads"; - case 25: return "Isolines"; - case 26: return "OutputVertices"; - case 27: return "OutputPoints"; - case 28: return "OutputLineStrip"; - case 29: return "OutputTriangleStrip"; - case 30: return "VecTypeHint"; - case 31: return "ContractionOff"; - case 32: return "Bad"; - - case 4446: return "PostDepthCoverage"; - case ExecutionModeCeiling: - default: return "Bad"; - } -} - -const int StorageClassCeiling = 13; - -const char* StorageClassString(int StorageClass) -{ - switch (StorageClass) { - case 0: return "UniformConstant"; - case 1: return "Input"; - case 2: return "Uniform"; - case 3: return "Output"; - case 4: return "Workgroup"; - case 5: return "CrossWorkgroup"; - case 6: return "Private"; - case 7: return "Function"; - case 8: return "Generic"; - case 9: return "PushConstant"; - case 10: return "AtomicCounter"; - case 11: return "Image"; - case 12: return "StorageBuffer"; - - case StorageClassCeiling: - default: return "Bad"; - } -} - -const int DecorationCeiling = 45; - -const char* DecorationString(int decoration) -{ - switch (decoration) { - case 0: return "RelaxedPrecision"; - case 1: return "SpecId"; - case 2: return "Block"; - case 3: return "BufferBlock"; - case 4: return "RowMajor"; - case 5: return "ColMajor"; - case 6: return "ArrayStride"; - case 7: return "MatrixStride"; - case 8: return "GLSLShared"; - case 9: return "GLSLPacked"; - case 10: return "CPacked"; - case 11: return "BuiltIn"; - case 12: return "Bad"; - case 13: return "NoPerspective"; - case 14: return "Flat"; - case 15: return "Patch"; - case 16: return "Centroid"; - case 17: return "Sample"; - case 18: return "Invariant"; - case 19: return "Restrict"; - case 20: return "Aliased"; - case 21: return "Volatile"; - case 22: return "Constant"; - case 23: return "Coherent"; - case 24: return "NonWritable"; - case 25: return "NonReadable"; - case 26: return "Uniform"; - case 27: return "Bad"; - case 28: return "SaturatedConversion"; - case 29: return "Stream"; - case 30: return "Location"; - case 31: return "Component"; - case 32: return "Index"; - case 33: return "Binding"; - case 34: return "DescriptorSet"; - case 35: return "Offset"; - case 36: return "XfbBuffer"; - case 37: return "XfbStride"; - case 38: return "FuncParamAttr"; - case 39: return "FP Rounding Mode"; - case 40: return "FP Fast Math Mode"; - case 41: return "Linkage Attributes"; - case 42: return "NoContraction"; - case 43: return "InputAttachmentIndex"; - case 44: return "Alignment"; - - case DecorationCeiling: - default: return "Bad"; - -#ifdef AMD_EXTENSIONS - case 4999: return "ExplicitInterpAMD"; -#endif -#ifdef NV_EXTENSIONS - case 5248: return "OverrideCoverageNV"; - case 5250: return "PassthroughNV"; - case 5252: return "ViewportRelativeNV"; - case 5256: return "SecondaryViewportRelativeNV"; -#endif - } -} - -const int BuiltInCeiling = 44; - -const char* BuiltInString(int builtIn) -{ - switch (builtIn) { - case 0: return "Position"; - case 1: return "PointSize"; - case 2: return "Bad"; - case 3: return "ClipDistance"; - case 4: return "CullDistance"; - case 5: return "VertexId"; - case 6: return "InstanceId"; - case 7: return "PrimitiveId"; - case 8: return "InvocationId"; - case 9: return "Layer"; - case 10: return "ViewportIndex"; - case 11: return "TessLevelOuter"; - case 12: return "TessLevelInner"; - case 13: return "TessCoord"; - case 14: return "PatchVertices"; - case 15: return "FragCoord"; - case 16: return "PointCoord"; - case 17: return "FrontFacing"; - case 18: return "SampleId"; - case 19: return "SamplePosition"; - case 20: return "SampleMask"; - case 21: return "Bad"; - case 22: return "FragDepth"; - case 23: return "HelperInvocation"; - case 24: return "NumWorkgroups"; - case 25: return "WorkgroupSize"; - case 26: return "WorkgroupId"; - case 27: return "LocalInvocationId"; - case 28: return "GlobalInvocationId"; - case 29: return "LocalInvocationIndex"; - case 30: return "WorkDim"; - case 31: return "GlobalSize"; - case 32: return "EnqueuedWorkgroupSize"; - case 33: return "GlobalOffset"; - case 34: return "GlobalLinearId"; - case 35: return "Bad"; - case 36: return "SubgroupSize"; - case 37: return "SubgroupMaxSize"; - case 38: return "NumSubgroups"; - case 39: return "NumEnqueuedSubgroups"; - case 40: return "SubgroupId"; - case 41: return "SubgroupLocalInvocationId"; - case 42: return "VertexIndex"; // TBD: put next to VertexId? - case 43: return "InstanceIndex"; // TBD: put next to InstanceId? - - case 4416: return "SubgroupEqMaskKHR"; - case 4417: return "SubgroupGeMaskKHR"; - case 4418: return "SubgroupGtMaskKHR"; - case 4419: return "SubgroupLeMaskKHR"; - case 4420: return "SubgroupLtMaskKHR"; - case 4438: return "DeviceIndex"; - case 4440: return "ViewIndex"; - case 4424: return "BaseVertex"; - case 4425: return "BaseInstance"; - case 4426: return "DrawIndex"; - case 5014: return "FragStencilRefEXT"; - -#ifdef AMD_EXTENSIONS - case 4992: return "BaryCoordNoPerspAMD"; - case 4993: return "BaryCoordNoPerspCentroidAMD"; - case 4994: return "BaryCoordNoPerspSampleAMD"; - case 4995: return "BaryCoordSmoothAMD"; - case 4996: return "BaryCoordSmoothCentroidAMD"; - case 4997: return "BaryCoordSmoothSampleAMD"; - case 4998: return "BaryCoordPullModelAMD"; -#endif - -#ifdef NV_EXTENSIONS - case 5253: return "ViewportMaskNV"; - case 5257: return "SecondaryPositionNV"; - case 5258: return "SecondaryViewportMaskNV"; - case 5261: return "PositionPerViewNV"; - case 5262: return "ViewportMaskPerViewNV"; -#endif - - case 5264: return "FullyCoveredEXT"; - - case BuiltInCeiling: - default: return "Bad"; - } -} - -const int DimensionCeiling = 7; - -const char* DimensionString(int dim) -{ - switch (dim) { - case 0: return "1D"; - case 1: return "2D"; - case 2: return "3D"; - case 3: return "Cube"; - case 4: return "Rect"; - case 5: return "Buffer"; - case 6: return "SubpassData"; - - case DimensionCeiling: - default: return "Bad"; - } -} - -const int SamplerAddressingModeCeiling = 5; - -const char* SamplerAddressingModeString(int mode) -{ - switch (mode) { - case 0: return "None"; - case 1: return "ClampToEdge"; - case 2: return "Clamp"; - case 3: return "Repeat"; - case 4: return "RepeatMirrored"; - - case SamplerAddressingModeCeiling: - default: return "Bad"; - } -} - -const int SamplerFilterModeCeiling = 2; - -const char* SamplerFilterModeString(int mode) -{ - switch (mode) { - case 0: return "Nearest"; - case 1: return "Linear"; - - case SamplerFilterModeCeiling: - default: return "Bad"; - } -} - -const int ImageFormatCeiling = 40; - -const char* ImageFormatString(int format) -{ - switch (format) { - case 0: return "Unknown"; - - // ES/Desktop float - case 1: return "Rgba32f"; - case 2: return "Rgba16f"; - case 3: return "R32f"; - case 4: return "Rgba8"; - case 5: return "Rgba8Snorm"; - - // Desktop float - case 6: return "Rg32f"; - case 7: return "Rg16f"; - case 8: return "R11fG11fB10f"; - case 9: return "R16f"; - case 10: return "Rgba16"; - case 11: return "Rgb10A2"; - case 12: return "Rg16"; - case 13: return "Rg8"; - case 14: return "R16"; - case 15: return "R8"; - case 16: return "Rgba16Snorm"; - case 17: return "Rg16Snorm"; - case 18: return "Rg8Snorm"; - case 19: return "R16Snorm"; - case 20: return "R8Snorm"; - - // ES/Desktop int - case 21: return "Rgba32i"; - case 22: return "Rgba16i"; - case 23: return "Rgba8i"; - case 24: return "R32i"; - - // Desktop int - case 25: return "Rg32i"; - case 26: return "Rg16i"; - case 27: return "Rg8i"; - case 28: return "R16i"; - case 29: return "R8i"; - - // ES/Desktop uint - case 30: return "Rgba32ui"; - case 31: return "Rgba16ui"; - case 32: return "Rgba8ui"; - case 33: return "R32ui"; - - // Desktop uint - case 34: return "Rgb10a2ui"; - case 35: return "Rg32ui"; - case 36: return "Rg16ui"; - case 37: return "Rg8ui"; - case 38: return "R16ui"; - case 39: return "R8ui"; - - case ImageFormatCeiling: - default: - return "Bad"; - } -} - -const int ImageChannelOrderCeiling = 19; - -const char* ImageChannelOrderString(int format) -{ - switch (format) { - case 0: return "R"; - case 1: return "A"; - case 2: return "RG"; - case 3: return "RA"; - case 4: return "RGB"; - case 5: return "RGBA"; - case 6: return "BGRA"; - case 7: return "ARGB"; - case 8: return "Intensity"; - case 9: return "Luminance"; - case 10: return "Rx"; - case 11: return "RGx"; - case 12: return "RGBx"; - case 13: return "Depth"; - case 14: return "DepthStencil"; - case 15: return "sRGB"; - case 16: return "sRGBx"; - case 17: return "sRGBA"; - case 18: return "sBGRA"; - - case ImageChannelOrderCeiling: - default: - return "Bad"; - } -} - -const int ImageChannelDataTypeCeiling = 17; - -const char* ImageChannelDataTypeString(int type) -{ - switch (type) - { - case 0: return "SnormInt8"; - case 1: return "SnormInt16"; - case 2: return "UnormInt8"; - case 3: return "UnormInt16"; - case 4: return "UnormShort565"; - case 5: return "UnormShort555"; - case 6: return "UnormInt101010"; - case 7: return "SignedInt8"; - case 8: return "SignedInt16"; - case 9: return "SignedInt32"; - case 10: return "UnsignedInt8"; - case 11: return "UnsignedInt16"; - case 12: return "UnsignedInt32"; - case 13: return "HalfFloat"; - case 14: return "Float"; - case 15: return "UnormInt24"; - case 16: return "UnormInt101010_2"; - - case ImageChannelDataTypeCeiling: - default: - return "Bad"; - } -} - -const int ImageOperandsCeiling = 8; - -const char* ImageOperandsString(int format) -{ - switch (format) { - case 0: return "Bias"; - case 1: return "Lod"; - case 2: return "Grad"; - case 3: return "ConstOffset"; - case 4: return "Offset"; - case 5: return "ConstOffsets"; - case 6: return "Sample"; - case 7: return "MinLod"; - - case ImageOperandsCeiling: - default: - return "Bad"; - } -} - -const int FPFastMathCeiling = 5; - -const char* FPFastMathString(int mode) -{ - switch (mode) { - case 0: return "NotNaN"; - case 1: return "NotInf"; - case 2: return "NSZ"; - case 3: return "AllowRecip"; - case 4: return "Fast"; - - case FPFastMathCeiling: - default: return "Bad"; - } -} - -const int FPRoundingModeCeiling = 4; - -const char* FPRoundingModeString(int mode) -{ - switch (mode) { - case 0: return "RTE"; - case 1: return "RTZ"; - case 2: return "RTP"; - case 3: return "RTN"; - - case FPRoundingModeCeiling: - default: return "Bad"; - } -} - -const int LinkageTypeCeiling = 2; - -const char* LinkageTypeString(int type) -{ - switch (type) { - case 0: return "Export"; - case 1: return "Import"; - - case LinkageTypeCeiling: - default: return "Bad"; - } -} - -const int FuncParamAttrCeiling = 8; - -const char* FuncParamAttrString(int attr) -{ - switch (attr) { - case 0: return "Zext"; - case 1: return "Sext"; - case 2: return "ByVal"; - case 3: return "Sret"; - case 4: return "NoAlias"; - case 5: return "NoCapture"; - case 6: return "NoWrite"; - case 7: return "NoReadWrite"; - - case FuncParamAttrCeiling: - default: return "Bad"; - } -} - -const int AccessQualifierCeiling = 3; - -const char* AccessQualifierString(int attr) -{ - switch (attr) { - case 0: return "ReadOnly"; - case 1: return "WriteOnly"; - case 2: return "ReadWrite"; - - case AccessQualifierCeiling: - default: return "Bad"; - } -} - -const int SelectControlCeiling = 2; - -const char* SelectControlString(int cont) -{ - switch (cont) { - case 0: return "Flatten"; - case 1: return "DontFlatten"; - - case SelectControlCeiling: - default: return "Bad"; - } -} - -const int LoopControlCeiling = 4; - -const char* LoopControlString(int cont) -{ - switch (cont) { - case 0: return "Unroll"; - case 1: return "DontUnroll"; - case 2: return "DependencyInfinite"; - case 3: return "DependencyLength"; - - case LoopControlCeiling: - default: return "Bad"; - } -} - -const int FunctionControlCeiling = 4; - -const char* FunctionControlString(int cont) -{ - switch (cont) { - case 0: return "Inline"; - case 1: return "DontInline"; - case 2: return "Pure"; - case 3: return "Const"; - - case FunctionControlCeiling: - default: return "Bad"; - } -} - -const int MemorySemanticsCeiling = 12; - -const char* MemorySemanticsString(int mem) -{ - // Note: No bits set (None) means "Relaxed" - switch (mem) { - case 0: return "Bad"; // Note: this is a placeholder for 'Consume' - case 1: return "Acquire"; - case 2: return "Release"; - case 3: return "AcquireRelease"; - case 4: return "SequentiallyConsistent"; - case 5: return "Bad"; // Note: reserved for future expansion - case 6: return "UniformMemory"; - case 7: return "SubgroupMemory"; - case 8: return "WorkgroupMemory"; - case 9: return "CrossWorkgroupMemory"; - case 10: return "AtomicCounterMemory"; - case 11: return "ImageMemory"; - - case MemorySemanticsCeiling: - default: return "Bad"; - } -} - -const int MemoryAccessCeiling = 3; - -const char* MemoryAccessString(int mem) -{ - switch (mem) { - case 0: return "Volatile"; - case 1: return "Aligned"; - case 2: return "Nontemporal"; - - case MemoryAccessCeiling: - default: return "Bad"; - } -} - -const int ScopeCeiling = 5; - -const char* ScopeString(int mem) -{ - switch (mem) { - case 0: return "CrossDevice"; - case 1: return "Device"; - case 2: return "Workgroup"; - case 3: return "Subgroup"; - case 4: return "Invocation"; - - case ScopeCeiling: - default: return "Bad"; - } -} - -const int GroupOperationCeiling = 3; - -const char* GroupOperationString(int gop) -{ - - switch (gop) - { - case 0: return "Reduce"; - case 1: return "InclusiveScan"; - case 2: return "ExclusiveScan"; - - case GroupOperationCeiling: - default: return "Bad"; - } -} - -const int KernelEnqueueFlagsCeiling = 3; - -const char* KernelEnqueueFlagsString(int flag) -{ - switch (flag) - { - case 0: return "NoWait"; - case 1: return "WaitKernel"; - case 2: return "WaitWorkGroup"; - - case KernelEnqueueFlagsCeiling: - default: return "Bad"; - } -} - -const int KernelProfilingInfoCeiling = 1; - -const char* KernelProfilingInfoString(int info) -{ - switch (info) - { - case 0: return "CmdExecTime"; - - case KernelProfilingInfoCeiling: - default: return "Bad"; - } -} - -const int CapabilityCeiling = 58; - -const char* CapabilityString(int info) -{ - switch (info) - { - case 0: return "Matrix"; - case 1: return "Shader"; - case 2: return "Geometry"; - case 3: return "Tessellation"; - case 4: return "Addresses"; - case 5: return "Linkage"; - case 6: return "Kernel"; - case 7: return "Vector16"; - case 8: return "Float16Buffer"; - case 9: return "Float16"; - case 10: return "Float64"; - case 11: return "Int64"; - case 12: return "Int64Atomics"; - case 13: return "ImageBasic"; - case 14: return "ImageReadWrite"; - case 15: return "ImageMipmap"; - case 16: return "Bad"; - case 17: return "Pipes"; - case 18: return "Groups"; - case 19: return "DeviceEnqueue"; - case 20: return "LiteralSampler"; - case 21: return "AtomicStorage"; - case 22: return "Int16"; - case 23: return "TessellationPointSize"; - case 24: return "GeometryPointSize"; - case 25: return "ImageGatherExtended"; - case 26: return "Bad"; - case 27: return "StorageImageMultisample"; - case 28: return "UniformBufferArrayDynamicIndexing"; - case 29: return "SampledImageArrayDynamicIndexing"; - case 30: return "StorageBufferArrayDynamicIndexing"; - case 31: return "StorageImageArrayDynamicIndexing"; - case 32: return "ClipDistance"; - case 33: return "CullDistance"; - case 34: return "ImageCubeArray"; - case 35: return "SampleRateShading"; - case 36: return "ImageRect"; - case 37: return "SampledRect"; - case 38: return "GenericPointer"; - case 39: return "Int8"; - case 40: return "InputAttachment"; - case 41: return "SparseResidency"; - case 42: return "MinLod"; - case 43: return "Sampled1D"; - case 44: return "Image1D"; - case 45: return "SampledCubeArray"; - case 46: return "SampledBuffer"; - case 47: return "ImageBuffer"; - case 48: return "ImageMSArray"; - case 49: return "StorageImageExtendedFormats"; - case 50: return "ImageQuery"; - case 51: return "DerivativeControl"; - case 52: return "InterpolationFunction"; - case 53: return "TransformFeedback"; - case 54: return "GeometryStreams"; - case 55: return "StorageImageReadWithoutFormat"; - case 56: return "StorageImageWriteWithoutFormat"; - case 57: return "MultiViewport"; - - case 4423: return "SubgroupBallotKHR"; - case 4427: return "DrawParameters"; - case 4431: return "SubgroupVoteKHR"; - - case 4433: return "StorageUniformBufferBlock16"; - case 4434: return "StorageUniform16"; - case 4435: return "StoragePushConstant16"; - case 4436: return "StorageInputOutput16"; - - case 4437: return "DeviceGroup"; - case 4439: return "MultiView"; - - case 5013: return "StencilExportEXT"; - -#ifdef AMD_EXTENSIONS - case 5009: return "ImageGatherBiasLodAMD"; - case 5010: return "FragmentMaskAMD"; - case 5015: return "ImageReadWriteLodAMD"; -#endif - - case 4445: return "AtomicStorageOps"; - - case 4447: return "SampleMaskPostDepthCoverage"; -#ifdef NV_EXTENSIONS - case 5251: return "GeometryShaderPassthroughNV"; - case 5254: return "ShaderViewportIndexLayerNV"; - case 5255: return "ShaderViewportMaskNV"; - case 5259: return "ShaderStereoViewNV"; - case 5260: return "PerViewAttributesNV"; -#endif - - case 5265: return "FragmentFullyCoveredEXT"; - - case CapabilityCeiling: - default: return "Bad"; - } -} - -const char* OpcodeString(int op) -{ - switch (op) { - case 0: return "OpNop"; - case 1: return "OpUndef"; - case 2: return "OpSourceContinued"; - case 3: return "OpSource"; - case 4: return "OpSourceExtension"; - case 5: return "OpName"; - case 6: return "OpMemberName"; - case 7: return "OpString"; - case 8: return "OpLine"; - case 9: return "Bad"; - case 10: return "OpExtension"; - case 11: return "OpExtInstImport"; - case 12: return "OpExtInst"; - case 13: return "Bad"; - case 14: return "OpMemoryModel"; - case 15: return "OpEntryPoint"; - case 16: return "OpExecutionMode"; - case 17: return "OpCapability"; - case 18: return "Bad"; - case 19: return "OpTypeVoid"; - case 20: return "OpTypeBool"; - case 21: return "OpTypeInt"; - case 22: return "OpTypeFloat"; - case 23: return "OpTypeVector"; - case 24: return "OpTypeMatrix"; - case 25: return "OpTypeImage"; - case 26: return "OpTypeSampler"; - case 27: return "OpTypeSampledImage"; - case 28: return "OpTypeArray"; - case 29: return "OpTypeRuntimeArray"; - case 30: return "OpTypeStruct"; - case 31: return "OpTypeOpaque"; - case 32: return "OpTypePointer"; - case 33: return "OpTypeFunction"; - case 34: return "OpTypeEvent"; - case 35: return "OpTypeDeviceEvent"; - case 36: return "OpTypeReserveId"; - case 37: return "OpTypeQueue"; - case 38: return "OpTypePipe"; - case 39: return "OpTypeForwardPointer"; - case 40: return "Bad"; - case 41: return "OpConstantTrue"; - case 42: return "OpConstantFalse"; - case 43: return "OpConstant"; - case 44: return "OpConstantComposite"; - case 45: return "OpConstantSampler"; - case 46: return "OpConstantNull"; - case 47: return "Bad"; - case 48: return "OpSpecConstantTrue"; - case 49: return "OpSpecConstantFalse"; - case 50: return "OpSpecConstant"; - case 51: return "OpSpecConstantComposite"; - case 52: return "OpSpecConstantOp"; - case 53: return "Bad"; - case 54: return "OpFunction"; - case 55: return "OpFunctionParameter"; - case 56: return "OpFunctionEnd"; - case 57: return "OpFunctionCall"; - case 58: return "Bad"; - case 59: return "OpVariable"; - case 60: return "OpImageTexelPointer"; - case 61: return "OpLoad"; - case 62: return "OpStore"; - case 63: return "OpCopyMemory"; - case 64: return "OpCopyMemorySized"; - case 65: return "OpAccessChain"; - case 66: return "OpInBoundsAccessChain"; - case 67: return "OpPtrAccessChain"; - case 68: return "OpArrayLength"; - case 69: return "OpGenericPtrMemSemantics"; - case 70: return "OpInBoundsPtrAccessChain"; - case 71: return "OpDecorate"; - case 72: return "OpMemberDecorate"; - case 73: return "OpDecorationGroup"; - case 74: return "OpGroupDecorate"; - case 75: return "OpGroupMemberDecorate"; - case 76: return "Bad"; - case 77: return "OpVectorExtractDynamic"; - case 78: return "OpVectorInsertDynamic"; - case 79: return "OpVectorShuffle"; - case 80: return "OpCompositeConstruct"; - case 81: return "OpCompositeExtract"; - case 82: return "OpCompositeInsert"; - case 83: return "OpCopyObject"; - case 84: return "OpTranspose"; - case 85: return "Bad"; - case 86: return "OpSampledImage"; - case 87: return "OpImageSampleImplicitLod"; - case 88: return "OpImageSampleExplicitLod"; - case 89: return "OpImageSampleDrefImplicitLod"; - case 90: return "OpImageSampleDrefExplicitLod"; - case 91: return "OpImageSampleProjImplicitLod"; - case 92: return "OpImageSampleProjExplicitLod"; - case 93: return "OpImageSampleProjDrefImplicitLod"; - case 94: return "OpImageSampleProjDrefExplicitLod"; - case 95: return "OpImageFetch"; - case 96: return "OpImageGather"; - case 97: return "OpImageDrefGather"; - case 98: return "OpImageRead"; - case 99: return "OpImageWrite"; - case 100: return "OpImage"; - case 101: return "OpImageQueryFormat"; - case 102: return "OpImageQueryOrder"; - case 103: return "OpImageQuerySizeLod"; - case 104: return "OpImageQuerySize"; - case 105: return "OpImageQueryLod"; - case 106: return "OpImageQueryLevels"; - case 107: return "OpImageQuerySamples"; - case 108: return "Bad"; - case 109: return "OpConvertFToU"; - case 110: return "OpConvertFToS"; - case 111: return "OpConvertSToF"; - case 112: return "OpConvertUToF"; - case 113: return "OpUConvert"; - case 114: return "OpSConvert"; - case 115: return "OpFConvert"; - case 116: return "OpQuantizeToF16"; - case 117: return "OpConvertPtrToU"; - case 118: return "OpSatConvertSToU"; - case 119: return "OpSatConvertUToS"; - case 120: return "OpConvertUToPtr"; - case 121: return "OpPtrCastToGeneric"; - case 122: return "OpGenericCastToPtr"; - case 123: return "OpGenericCastToPtrExplicit"; - case 124: return "OpBitcast"; - case 125: return "Bad"; - case 126: return "OpSNegate"; - case 127: return "OpFNegate"; - case 128: return "OpIAdd"; - case 129: return "OpFAdd"; - case 130: return "OpISub"; - case 131: return "OpFSub"; - case 132: return "OpIMul"; - case 133: return "OpFMul"; - case 134: return "OpUDiv"; - case 135: return "OpSDiv"; - case 136: return "OpFDiv"; - case 137: return "OpUMod"; - case 138: return "OpSRem"; - case 139: return "OpSMod"; - case 140: return "OpFRem"; - case 141: return "OpFMod"; - case 142: return "OpVectorTimesScalar"; - case 143: return "OpMatrixTimesScalar"; - case 144: return "OpVectorTimesMatrix"; - case 145: return "OpMatrixTimesVector"; - case 146: return "OpMatrixTimesMatrix"; - case 147: return "OpOuterProduct"; - case 148: return "OpDot"; - case 149: return "OpIAddCarry"; - case 150: return "OpISubBorrow"; - case 151: return "OpUMulExtended"; - case 152: return "OpSMulExtended"; - case 153: return "Bad"; - case 154: return "OpAny"; - case 155: return "OpAll"; - case 156: return "OpIsNan"; - case 157: return "OpIsInf"; - case 158: return "OpIsFinite"; - case 159: return "OpIsNormal"; - case 160: return "OpSignBitSet"; - case 161: return "OpLessOrGreater"; - case 162: return "OpOrdered"; - case 163: return "OpUnordered"; - case 164: return "OpLogicalEqual"; - case 165: return "OpLogicalNotEqual"; - case 166: return "OpLogicalOr"; - case 167: return "OpLogicalAnd"; - case 168: return "OpLogicalNot"; - case 169: return "OpSelect"; - case 170: return "OpIEqual"; - case 171: return "OpINotEqual"; - case 172: return "OpUGreaterThan"; - case 173: return "OpSGreaterThan"; - case 174: return "OpUGreaterThanEqual"; - case 175: return "OpSGreaterThanEqual"; - case 176: return "OpULessThan"; - case 177: return "OpSLessThan"; - case 178: return "OpULessThanEqual"; - case 179: return "OpSLessThanEqual"; - case 180: return "OpFOrdEqual"; - case 181: return "OpFUnordEqual"; - case 182: return "OpFOrdNotEqual"; - case 183: return "OpFUnordNotEqual"; - case 184: return "OpFOrdLessThan"; - case 185: return "OpFUnordLessThan"; - case 186: return "OpFOrdGreaterThan"; - case 187: return "OpFUnordGreaterThan"; - case 188: return "OpFOrdLessThanEqual"; - case 189: return "OpFUnordLessThanEqual"; - case 190: return "OpFOrdGreaterThanEqual"; - case 191: return "OpFUnordGreaterThanEqual"; - case 192: return "Bad"; - case 193: return "Bad"; - case 194: return "OpShiftRightLogical"; - case 195: return "OpShiftRightArithmetic"; - case 196: return "OpShiftLeftLogical"; - case 197: return "OpBitwiseOr"; - case 198: return "OpBitwiseXor"; - case 199: return "OpBitwiseAnd"; - case 200: return "OpNot"; - case 201: return "OpBitFieldInsert"; - case 202: return "OpBitFieldSExtract"; - case 203: return "OpBitFieldUExtract"; - case 204: return "OpBitReverse"; - case 205: return "OpBitCount"; - case 206: return "Bad"; - case 207: return "OpDPdx"; - case 208: return "OpDPdy"; - case 209: return "OpFwidth"; - case 210: return "OpDPdxFine"; - case 211: return "OpDPdyFine"; - case 212: return "OpFwidthFine"; - case 213: return "OpDPdxCoarse"; - case 214: return "OpDPdyCoarse"; - case 215: return "OpFwidthCoarse"; - case 216: return "Bad"; - case 217: return "Bad"; - case 218: return "OpEmitVertex"; - case 219: return "OpEndPrimitive"; - case 220: return "OpEmitStreamVertex"; - case 221: return "OpEndStreamPrimitive"; - case 222: return "Bad"; - case 223: return "Bad"; - case 224: return "OpControlBarrier"; - case 225: return "OpMemoryBarrier"; - case 226: return "Bad"; - case 227: return "OpAtomicLoad"; - case 228: return "OpAtomicStore"; - case 229: return "OpAtomicExchange"; - case 230: return "OpAtomicCompareExchange"; - case 231: return "OpAtomicCompareExchangeWeak"; - case 232: return "OpAtomicIIncrement"; - case 233: return "OpAtomicIDecrement"; - case 234: return "OpAtomicIAdd"; - case 235: return "OpAtomicISub"; - case 236: return "OpAtomicSMin"; - case 237: return "OpAtomicUMin"; - case 238: return "OpAtomicSMax"; - case 239: return "OpAtomicUMax"; - case 240: return "OpAtomicAnd"; - case 241: return "OpAtomicOr"; - case 242: return "OpAtomicXor"; - case 243: return "Bad"; - case 244: return "Bad"; - case 245: return "OpPhi"; - case 246: return "OpLoopMerge"; - case 247: return "OpSelectionMerge"; - case 248: return "OpLabel"; - case 249: return "OpBranch"; - case 250: return "OpBranchConditional"; - case 251: return "OpSwitch"; - case 252: return "OpKill"; - case 253: return "OpReturn"; - case 254: return "OpReturnValue"; - case 255: return "OpUnreachable"; - case 256: return "OpLifetimeStart"; - case 257: return "OpLifetimeStop"; - case 258: return "Bad"; - case 259: return "OpGroupAsyncCopy"; - case 260: return "OpGroupWaitEvents"; - case 261: return "OpGroupAll"; - case 262: return "OpGroupAny"; - case 263: return "OpGroupBroadcast"; - case 264: return "OpGroupIAdd"; - case 265: return "OpGroupFAdd"; - case 266: return "OpGroupFMin"; - case 267: return "OpGroupUMin"; - case 268: return "OpGroupSMin"; - case 269: return "OpGroupFMax"; - case 270: return "OpGroupUMax"; - case 271: return "OpGroupSMax"; - case 272: return "Bad"; - case 273: return "Bad"; - case 274: return "OpReadPipe"; - case 275: return "OpWritePipe"; - case 276: return "OpReservedReadPipe"; - case 277: return "OpReservedWritePipe"; - case 278: return "OpReserveReadPipePackets"; - case 279: return "OpReserveWritePipePackets"; - case 280: return "OpCommitReadPipe"; - case 281: return "OpCommitWritePipe"; - case 282: return "OpIsValidReserveId"; - case 283: return "OpGetNumPipePackets"; - case 284: return "OpGetMaxPipePackets"; - case 285: return "OpGroupReserveReadPipePackets"; - case 286: return "OpGroupReserveWritePipePackets"; - case 287: return "OpGroupCommitReadPipe"; - case 288: return "OpGroupCommitWritePipe"; - case 289: return "Bad"; - case 290: return "Bad"; - case 291: return "OpEnqueueMarker"; - case 292: return "OpEnqueueKernel"; - case 293: return "OpGetKernelNDrangeSubGroupCount"; - case 294: return "OpGetKernelNDrangeMaxSubGroupSize"; - case 295: return "OpGetKernelWorkGroupSize"; - case 296: return "OpGetKernelPreferredWorkGroupSizeMultiple"; - case 297: return "OpRetainEvent"; - case 298: return "OpReleaseEvent"; - case 299: return "OpCreateUserEvent"; - case 300: return "OpIsValidEvent"; - case 301: return "OpSetUserEventStatus"; - case 302: return "OpCaptureEventProfilingInfo"; - case 303: return "OpGetDefaultQueue"; - case 304: return "OpBuildNDRange"; - case 305: return "OpImageSparseSampleImplicitLod"; - case 306: return "OpImageSparseSampleExplicitLod"; - case 307: return "OpImageSparseSampleDrefImplicitLod"; - case 308: return "OpImageSparseSampleDrefExplicitLod"; - case 309: return "OpImageSparseSampleProjImplicitLod"; - case 310: return "OpImageSparseSampleProjExplicitLod"; - case 311: return "OpImageSparseSampleProjDrefImplicitLod"; - case 312: return "OpImageSparseSampleProjDrefExplicitLod"; - case 313: return "OpImageSparseFetch"; - case 314: return "OpImageSparseGather"; - case 315: return "OpImageSparseDrefGather"; - case 316: return "OpImageSparseTexelsResident"; - case 317: return "OpNoLine"; - case 318: return "OpAtomicFlagTestAndSet"; - case 319: return "OpAtomicFlagClear"; - case 320: return "OpImageSparseRead"; - - case 4421: return "OpSubgroupBallotKHR"; - case 4422: return "OpSubgroupFirstInvocationKHR"; - case 4428: return "OpSubgroupAllKHR"; - case 4429: return "OpSubgroupAnyKHR"; - case 4430: return "OpSubgroupAllEqualKHR"; - case 4432: return "OpSubgroupReadInvocationKHR"; - -#ifdef AMD_EXTENSIONS - case 5000: return "OpGroupIAddNonUniformAMD"; - case 5001: return "OpGroupFAddNonUniformAMD"; - case 5002: return "OpGroupFMinNonUniformAMD"; - case 5003: return "OpGroupUMinNonUniformAMD"; - case 5004: return "OpGroupSMinNonUniformAMD"; - case 5005: return "OpGroupFMaxNonUniformAMD"; - case 5006: return "OpGroupUMaxNonUniformAMD"; - case 5007: return "OpGroupSMaxNonUniformAMD"; - - case 5011: return "OpFragmentMaskFetchAMD"; - case 5012: return "OpFragmentFetchAMD"; -#endif - - case OpcodeCeiling: - default: - return "Bad"; - } -} - -// The set of objects that hold all the instruction/operand -// parameterization information. -InstructionParameters InstructionDesc[OpCodeMask + 1]; -OperandParameters ExecutionModeOperands[ExecutionModeCeiling]; -OperandParameters DecorationOperands[DecorationCeiling]; - -EnumDefinition OperandClassParams[OperandCount]; -EnumParameters ExecutionModelParams[ExecutionModelCeiling]; -EnumParameters AddressingParams[AddressingModelCeiling]; -EnumParameters MemoryParams[MemoryModelCeiling]; -EnumParameters ExecutionModeParams[ExecutionModeCeiling]; -EnumParameters StorageParams[StorageClassCeiling]; -EnumParameters SamplerAddressingModeParams[SamplerAddressingModeCeiling]; -EnumParameters SamplerFilterModeParams[SamplerFilterModeCeiling]; -EnumParameters ImageFormatParams[ImageFormatCeiling]; -EnumParameters ImageChannelOrderParams[ImageChannelOrderCeiling]; -EnumParameters ImageChannelDataTypeParams[ImageChannelDataTypeCeiling]; -EnumParameters ImageOperandsParams[ImageOperandsCeiling]; -EnumParameters FPFastMathParams[FPFastMathCeiling]; -EnumParameters FPRoundingModeParams[FPRoundingModeCeiling]; -EnumParameters LinkageTypeParams[LinkageTypeCeiling]; -EnumParameters DecorationParams[DecorationCeiling]; -EnumParameters BuiltInParams[BuiltInCeiling]; -EnumParameters DimensionalityParams[DimensionCeiling]; -EnumParameters FuncParamAttrParams[FuncParamAttrCeiling]; -EnumParameters AccessQualifierParams[AccessQualifierCeiling]; -EnumParameters GroupOperationParams[GroupOperationCeiling]; -EnumParameters LoopControlParams[FunctionControlCeiling]; -EnumParameters SelectionControlParams[SelectControlCeiling]; -EnumParameters FunctionControlParams[FunctionControlCeiling]; -EnumParameters MemorySemanticsParams[MemorySemanticsCeiling]; -EnumParameters MemoryAccessParams[MemoryAccessCeiling]; -EnumParameters ScopeParams[ScopeCeiling]; -EnumParameters KernelEnqueueFlagsParams[KernelEnqueueFlagsCeiling]; -EnumParameters KernelProfilingInfoParams[KernelProfilingInfoCeiling]; -EnumParameters CapabilityParams[CapabilityCeiling]; - -// Set up all the parameterizing descriptions of the opcodes, operands, etc. -void Parameterize() -{ - // only do this once. - static bool initialized = false; - if (initialized) - return; - initialized = true; - - // Exceptions to having a result and a resulting type . - // (Everything is initialized to have both). - - InstructionDesc[OpNop].setResultAndType(false, false); - InstructionDesc[OpSource].setResultAndType(false, false); - InstructionDesc[OpSourceContinued].setResultAndType(false, false); - InstructionDesc[OpSourceExtension].setResultAndType(false, false); - InstructionDesc[OpExtension].setResultAndType(false, false); - InstructionDesc[OpExtInstImport].setResultAndType(true, false); - InstructionDesc[OpCapability].setResultAndType(false, false); - InstructionDesc[OpMemoryModel].setResultAndType(false, false); - InstructionDesc[OpEntryPoint].setResultAndType(false, false); - InstructionDesc[OpExecutionMode].setResultAndType(false, false); - InstructionDesc[OpTypeVoid].setResultAndType(true, false); - InstructionDesc[OpTypeBool].setResultAndType(true, false); - InstructionDesc[OpTypeInt].setResultAndType(true, false); - InstructionDesc[OpTypeFloat].setResultAndType(true, false); - InstructionDesc[OpTypeVector].setResultAndType(true, false); - InstructionDesc[OpTypeMatrix].setResultAndType(true, false); - InstructionDesc[OpTypeImage].setResultAndType(true, false); - InstructionDesc[OpTypeSampler].setResultAndType(true, false); - InstructionDesc[OpTypeSampledImage].setResultAndType(true, false); - InstructionDesc[OpTypeArray].setResultAndType(true, false); - InstructionDesc[OpTypeRuntimeArray].setResultAndType(true, false); - InstructionDesc[OpTypeStruct].setResultAndType(true, false); - InstructionDesc[OpTypeOpaque].setResultAndType(true, false); - InstructionDesc[OpTypePointer].setResultAndType(true, false); - InstructionDesc[OpTypeForwardPointer].setResultAndType(false, false); - InstructionDesc[OpTypeFunction].setResultAndType(true, false); - InstructionDesc[OpTypeEvent].setResultAndType(true, false); - InstructionDesc[OpTypeDeviceEvent].setResultAndType(true, false); - InstructionDesc[OpTypeReserveId].setResultAndType(true, false); - InstructionDesc[OpTypeQueue].setResultAndType(true, false); - InstructionDesc[OpTypePipe].setResultAndType(true, false); - InstructionDesc[OpFunctionEnd].setResultAndType(false, false); - InstructionDesc[OpStore].setResultAndType(false, false); - InstructionDesc[OpImageWrite].setResultAndType(false, false); - InstructionDesc[OpDecorationGroup].setResultAndType(true, false); - InstructionDesc[OpDecorate].setResultAndType(false, false); - InstructionDesc[OpMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpGroupDecorate].setResultAndType(false, false); - InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpName].setResultAndType(false, false); - InstructionDesc[OpMemberName].setResultAndType(false, false); - InstructionDesc[OpString].setResultAndType(true, false); - InstructionDesc[OpLine].setResultAndType(false, false); - InstructionDesc[OpNoLine].setResultAndType(false, false); - InstructionDesc[OpCopyMemory].setResultAndType(false, false); - InstructionDesc[OpCopyMemorySized].setResultAndType(false, false); - InstructionDesc[OpEmitVertex].setResultAndType(false, false); - InstructionDesc[OpEndPrimitive].setResultAndType(false, false); - InstructionDesc[OpEmitStreamVertex].setResultAndType(false, false); - InstructionDesc[OpEndStreamPrimitive].setResultAndType(false, false); - InstructionDesc[OpControlBarrier].setResultAndType(false, false); - InstructionDesc[OpMemoryBarrier].setResultAndType(false, false); - InstructionDesc[OpAtomicStore].setResultAndType(false, false); - InstructionDesc[OpLoopMerge].setResultAndType(false, false); - InstructionDesc[OpSelectionMerge].setResultAndType(false, false); - InstructionDesc[OpLabel].setResultAndType(true, false); - InstructionDesc[OpBranch].setResultAndType(false, false); - InstructionDesc[OpBranchConditional].setResultAndType(false, false); - InstructionDesc[OpSwitch].setResultAndType(false, false); - InstructionDesc[OpKill].setResultAndType(false, false); - InstructionDesc[OpReturn].setResultAndType(false, false); - InstructionDesc[OpReturnValue].setResultAndType(false, false); - InstructionDesc[OpUnreachable].setResultAndType(false, false); - InstructionDesc[OpLifetimeStart].setResultAndType(false, false); - InstructionDesc[OpLifetimeStop].setResultAndType(false, false); - InstructionDesc[OpCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCaptureEventProfilingInfo].setResultAndType(false, false); - InstructionDesc[OpSetUserEventStatus].setResultAndType(false, false); - InstructionDesc[OpRetainEvent].setResultAndType(false, false); - InstructionDesc[OpReleaseEvent].setResultAndType(false, false); - InstructionDesc[OpGroupWaitEvents].setResultAndType(false, false); - InstructionDesc[OpAtomicFlagClear].setResultAndType(false, false); - - // Specific additional context-dependent operands - - ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <>'"); - - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeOutputVertices].push(OperandLiteralNumber, "'Vertex count'"); - ExecutionModeOperands[ExecutionModeVecTypeHint].push(OperandLiteralNumber, "'Vector type'"); - - DecorationOperands[DecorationStream].push(OperandLiteralNumber, "'Stream Number'"); - DecorationOperands[DecorationLocation].push(OperandLiteralNumber, "'Location'"); - DecorationOperands[DecorationComponent].push(OperandLiteralNumber, "'Component'"); - DecorationOperands[DecorationIndex].push(OperandLiteralNumber, "'Index'"); - DecorationOperands[DecorationBinding].push(OperandLiteralNumber, "'Binding Point'"); - DecorationOperands[DecorationDescriptorSet].push(OperandLiteralNumber, "'Descriptor Set'"); - DecorationOperands[DecorationOffset].push(OperandLiteralNumber, "'Byte Offset'"); - DecorationOperands[DecorationXfbBuffer].push(OperandLiteralNumber, "'XFB Buffer Number'"); - DecorationOperands[DecorationXfbStride].push(OperandLiteralNumber, "'XFB Stride'"); - DecorationOperands[DecorationArrayStride].push(OperandLiteralNumber, "'Array Stride'"); - DecorationOperands[DecorationMatrixStride].push(OperandLiteralNumber, "'Matrix Stride'"); - DecorationOperands[DecorationBuiltIn].push(OperandLiteralNumber, "See <>"); - DecorationOperands[DecorationFPRoundingMode].push(OperandFPRoundingMode, "'Floating-Point Rounding Mode'"); - DecorationOperands[DecorationFPFastMathMode].push(OperandFPFastMath, "'Fast-Math Mode'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLiteralString, "'Name'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLinkageType, "'Linkage Type'"); - DecorationOperands[DecorationFuncParamAttr].push(OperandFuncParamAttr, "'Function Parameter Attribute'"); - DecorationOperands[DecorationSpecId].push(OperandLiteralNumber, "'Specialization Constant ID'"); - DecorationOperands[DecorationInputAttachmentIndex].push(OperandLiteralNumber, "'Attachment Index'"); - DecorationOperands[DecorationAlignment].push(OperandLiteralNumber, "'Alignment'"); - - OperandClassParams[OperandSource].set(SourceLanguageCeiling, SourceString, 0); - OperandClassParams[OperandExecutionModel].set(ExecutionModelCeiling, ExecutionModelString, ExecutionModelParams); - OperandClassParams[OperandAddressing].set(AddressingModelCeiling, AddressingString, AddressingParams); - OperandClassParams[OperandMemory].set(MemoryModelCeiling, MemoryString, MemoryParams); - OperandClassParams[OperandExecutionMode].set(ExecutionModeCeiling, ExecutionModeString, ExecutionModeParams); - OperandClassParams[OperandExecutionMode].setOperands(ExecutionModeOperands); - OperandClassParams[OperandStorage].set(StorageClassCeiling, StorageClassString, StorageParams); - OperandClassParams[OperandDimensionality].set(DimensionCeiling, DimensionString, DimensionalityParams); - OperandClassParams[OperandSamplerAddressingMode].set(SamplerAddressingModeCeiling, SamplerAddressingModeString, SamplerAddressingModeParams); - OperandClassParams[OperandSamplerFilterMode].set(SamplerFilterModeCeiling, SamplerFilterModeString, SamplerFilterModeParams); - OperandClassParams[OperandSamplerImageFormat].set(ImageFormatCeiling, ImageFormatString, ImageFormatParams); - OperandClassParams[OperandImageChannelOrder].set(ImageChannelOrderCeiling, ImageChannelOrderString, ImageChannelOrderParams); - OperandClassParams[OperandImageChannelDataType].set(ImageChannelDataTypeCeiling, ImageChannelDataTypeString, ImageChannelDataTypeParams); - OperandClassParams[OperandImageOperands].set(ImageOperandsCeiling, ImageOperandsString, ImageOperandsParams, true); - OperandClassParams[OperandFPFastMath].set(FPFastMathCeiling, FPFastMathString, FPFastMathParams, true); - OperandClassParams[OperandFPRoundingMode].set(FPRoundingModeCeiling, FPRoundingModeString, FPRoundingModeParams); - OperandClassParams[OperandLinkageType].set(LinkageTypeCeiling, LinkageTypeString, LinkageTypeParams); - OperandClassParams[OperandFuncParamAttr].set(FuncParamAttrCeiling, FuncParamAttrString, FuncParamAttrParams); - OperandClassParams[OperandAccessQualifier].set(AccessQualifierCeiling, AccessQualifierString, AccessQualifierParams); - OperandClassParams[OperandDecoration].set(DecorationCeiling, DecorationString, DecorationParams); - OperandClassParams[OperandDecoration].setOperands(DecorationOperands); - OperandClassParams[OperandBuiltIn].set(BuiltInCeiling, BuiltInString, BuiltInParams); - OperandClassParams[OperandSelect].set(SelectControlCeiling, SelectControlString, SelectionControlParams, true); - OperandClassParams[OperandLoop].set(LoopControlCeiling, LoopControlString, LoopControlParams, true); - OperandClassParams[OperandFunction].set(FunctionControlCeiling, FunctionControlString, FunctionControlParams, true); - OperandClassParams[OperandMemorySemantics].set(MemorySemanticsCeiling, MemorySemanticsString, MemorySemanticsParams, true); - OperandClassParams[OperandMemoryAccess].set(MemoryAccessCeiling, MemoryAccessString, MemoryAccessParams, true); - OperandClassParams[OperandScope].set(ScopeCeiling, ScopeString, ScopeParams); - OperandClassParams[OperandGroupOperation].set(GroupOperationCeiling, GroupOperationString, GroupOperationParams); - OperandClassParams[OperandKernelEnqueueFlags].set(KernelEnqueueFlagsCeiling, KernelEnqueueFlagsString, KernelEnqueueFlagsParams); - OperandClassParams[OperandKernelProfilingInfo].set(KernelProfilingInfoCeiling, KernelProfilingInfoString, KernelProfilingInfoParams, true); - OperandClassParams[OperandCapability].set(CapabilityCeiling, CapabilityString, CapabilityParams); - OperandClassParams[OperandOpcode].set(OpcodeCeiling, OpcodeString, 0); - - CapabilityParams[CapabilityShader].caps.push_back(CapabilityMatrix); - CapabilityParams[CapabilityGeometry].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityTessellation].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityVector16].caps.push_back(CapabilityKernel); - CapabilityParams[CapabilityFloat16Buffer].caps.push_back(CapabilityKernel); - CapabilityParams[CapabilityInt64Atomics].caps.push_back(CapabilityInt64); - CapabilityParams[CapabilityImageBasic].caps.push_back(CapabilityKernel); - CapabilityParams[CapabilityImageReadWrite].caps.push_back(CapabilityImageBasic); - CapabilityParams[CapabilityImageMipmap].caps.push_back(CapabilityImageBasic); - CapabilityParams[CapabilityPipes].caps.push_back(CapabilityKernel); - CapabilityParams[CapabilityDeviceEnqueue].caps.push_back(CapabilityKernel); - CapabilityParams[CapabilityLiteralSampler].caps.push_back(CapabilityKernel); - CapabilityParams[CapabilityAtomicStorage].caps.push_back(CapabilityShader); - CapabilityParams[CapabilitySampleRateShading].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityTessellationPointSize].caps.push_back(CapabilityTessellation); - CapabilityParams[CapabilityGeometryPointSize].caps.push_back(CapabilityGeometry); - CapabilityParams[CapabilityImageGatherExtended].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityStorageImageExtendedFormats].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityStorageImageMultisample].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityUniformBufferArrayDynamicIndexing].caps.push_back(CapabilityShader); - CapabilityParams[CapabilitySampledImageArrayDynamicIndexing].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityStorageBufferArrayDynamicIndexing].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityStorageImageArrayDynamicIndexing].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityClipDistance].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityCullDistance].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityGenericPointer].caps.push_back(CapabilityAddresses); - CapabilityParams[CapabilityInt8].caps.push_back(CapabilityKernel); - CapabilityParams[CapabilityInputAttachment].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityMinLod].caps.push_back(CapabilityShader); - CapabilityParams[CapabilitySparseResidency].caps.push_back(CapabilityShader); - CapabilityParams[CapabilitySampled1D].caps.push_back(CapabilityShader); - CapabilityParams[CapabilitySampledRect].caps.push_back(CapabilityShader); - CapabilityParams[CapabilitySampledBuffer].caps.push_back(CapabilityShader); - CapabilityParams[CapabilitySampledCubeArray].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityImageMSArray].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityImage1D].caps.push_back(CapabilitySampled1D); - CapabilityParams[CapabilityImageRect].caps.push_back(CapabilitySampledRect); - CapabilityParams[CapabilityImageBuffer].caps.push_back(CapabilitySampledBuffer); - CapabilityParams[CapabilityImageCubeArray].caps.push_back(CapabilitySampledCubeArray); - CapabilityParams[CapabilityImageQuery].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityDerivativeControl].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityInterpolationFunction].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityTransformFeedback].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityGeometryStreams].caps.push_back(CapabilityGeometry); - CapabilityParams[CapabilityStorageImageReadWithoutFormat].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityStorageImageWriteWithoutFormat].caps.push_back(CapabilityShader); - CapabilityParams[CapabilityMultiViewport].caps.push_back(CapabilityGeometry); - - AddressingParams[AddressingModelPhysical32].caps.push_back(CapabilityAddresses); - AddressingParams[AddressingModelPhysical64].caps.push_back(CapabilityAddresses); - - MemoryParams[MemoryModelSimple].caps.push_back(CapabilityShader); - MemoryParams[MemoryModelGLSL450].caps.push_back(CapabilityShader); - MemoryParams[MemoryModelOpenCL].caps.push_back(CapabilityKernel); - - MemorySemanticsParams[MemorySemanticsUniformMemoryShift].caps.push_back(CapabilityShader); - MemorySemanticsParams[MemorySemanticsAtomicCounterMemoryShift].caps.push_back(CapabilityAtomicStorage); - - ExecutionModelParams[ExecutionModelVertex].caps.push_back(CapabilityShader); - ExecutionModelParams[ExecutionModelTessellationControl].caps.push_back(CapabilityTessellation); - ExecutionModelParams[ExecutionModelTessellationEvaluation].caps.push_back(CapabilityTessellation); - ExecutionModelParams[ExecutionModelGeometry].caps.push_back(CapabilityGeometry); - ExecutionModelParams[ExecutionModelFragment].caps.push_back(CapabilityShader); - ExecutionModelParams[ExecutionModelGLCompute].caps.push_back(CapabilityShader); - ExecutionModelParams[ExecutionModelKernel].caps.push_back(CapabilityKernel); - - // Storage capabilites - StorageParams[StorageClassInput].caps.push_back(CapabilityShader); - StorageParams[StorageClassUniform].caps.push_back(CapabilityShader); - StorageParams[StorageClassOutput].caps.push_back(CapabilityShader); - StorageParams[StorageClassPrivate].caps.push_back(CapabilityShader); - StorageParams[StorageClassGeneric].caps.push_back(CapabilityKernel); - StorageParams[StorageClassAtomicCounter].caps.push_back(CapabilityAtomicStorage); - StorageParams[StorageClassPushConstant].caps.push_back(CapabilityShader); - - // Sampler Filter & Addressing mode capabilities - SamplerAddressingModeParams[SamplerAddressingModeNone].caps.push_back(CapabilityKernel); - SamplerAddressingModeParams[SamplerAddressingModeClampToEdge].caps.push_back(CapabilityKernel); - SamplerAddressingModeParams[SamplerAddressingModeClamp].caps.push_back(CapabilityKernel); - SamplerAddressingModeParams[SamplerAddressingModeRepeat].caps.push_back(CapabilityKernel); - SamplerAddressingModeParams[SamplerAddressingModeRepeatMirrored].caps.push_back(CapabilityKernel); - - SamplerFilterModeParams[SamplerFilterModeNearest].caps.push_back(CapabilityKernel); - SamplerFilterModeParams[SamplerFilterModeLinear].caps.push_back(CapabilityKernel); - - // image format capabilities - - // ES/Desktop float - ImageFormatParams[ImageFormatRgba32f].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatRgba16f].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatR32f].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatRgba8].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatRgba8Snorm].caps.push_back(CapabilityShader); - - // Desktop float - ImageFormatParams[ImageFormatRg32f].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg16f].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR11fG11fB10f].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR16f].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRgba16].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRgb10A2].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg16].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg8].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR16].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR8].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRgba16Snorm].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg16Snorm].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg8Snorm].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR16Snorm].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR8Snorm].caps.push_back(CapabilityStorageImageExtendedFormats); - - // ES/Desktop int - ImageFormatParams[ImageFormatRgba32i].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatRgba16i].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatRgba8i].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatR32i].caps.push_back(CapabilityShader); - - // Desktop int - ImageFormatParams[ImageFormatRg32i].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg16i].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg8i].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR16i].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR8i].caps.push_back(CapabilityStorageImageExtendedFormats); - - // ES/Desktop uint - ImageFormatParams[ImageFormatRgba32ui].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatRgba16ui].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatRgba8ui].caps.push_back(CapabilityShader); - ImageFormatParams[ImageFormatR32ui].caps.push_back(CapabilityShader); - - // Desktop uint - ImageFormatParams[ImageFormatRgb10a2ui].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg32ui].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg16ui].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatRg8ui].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR16ui].caps.push_back(CapabilityStorageImageExtendedFormats); - ImageFormatParams[ImageFormatR8ui].caps.push_back(CapabilityStorageImageExtendedFormats); - - // image channel order capabilities - for (int i = 0; i < ImageChannelOrderCeiling; ++i) { - ImageChannelOrderParams[i].caps.push_back(CapabilityKernel); - } - - // image channel type capabilities - for (int i = 0; i < ImageChannelDataTypeCeiling; ++i) { - ImageChannelDataTypeParams[i].caps.push_back(CapabilityKernel); - } - - // image lookup operands - ImageOperandsParams[ImageOperandsBiasShift].caps.push_back(CapabilityShader); - ImageOperandsParams[ImageOperandsOffsetShift].caps.push_back(CapabilityImageGatherExtended); - ImageOperandsParams[ImageOperandsMinLodShift].caps.push_back(CapabilityMinLod); - - // fast math flags capabilities - for (int i = 0; i < FPFastMathCeiling; ++i) { - FPFastMathParams[i].caps.push_back(CapabilityKernel); - } - - // fp rounding mode capabilities - for (int i = 0; i < FPRoundingModeCeiling; ++i) { - FPRoundingModeParams[i].caps.push_back(CapabilityKernel); - } - - // linkage types - for (int i = 0; i < LinkageTypeCeiling; ++i) { - LinkageTypeParams[i].caps.push_back(CapabilityLinkage); - } - - // function argument types - for (int i = 0; i < FuncParamAttrCeiling; ++i) { - FuncParamAttrParams[i].caps.push_back(CapabilityKernel); - } - - // function argument types - for (int i = 0; i < AccessQualifierCeiling; ++i) { - AccessQualifierParams[i].caps.push_back(CapabilityKernel); - } - - ExecutionModeParams[ExecutionModeInvocations].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeSpacingEqual].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeSpacingFractionalEven].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeSpacingFractionalOdd].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeVertexOrderCw].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeVertexOrderCcw].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModePixelCenterInteger].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModeOriginUpperLeft].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModeOriginLowerLeft].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModeEarlyFragmentTests].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModePointMode].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeXfb].caps.push_back(CapabilityTransformFeedback); - ExecutionModeParams[ExecutionModeDepthReplacing].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModeDepthGreater].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModeDepthLess].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModeDepthUnchanged].caps.push_back(CapabilityShader); - ExecutionModeParams[ExecutionModeLocalSizeHint].caps.push_back(CapabilityKernel); - ExecutionModeParams[ExecutionModeInputPoints].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeInputLines].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeInputLinesAdjacency].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeTriangles].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeTriangles].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeInputTrianglesAdjacency].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeQuads].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeIsolines].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeOutputVertices].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeOutputVertices].caps.push_back(CapabilityTessellation); - ExecutionModeParams[ExecutionModeOutputPoints].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeOutputLineStrip].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeOutputTriangleStrip].caps.push_back(CapabilityGeometry); - ExecutionModeParams[ExecutionModeVecTypeHint].caps.push_back(CapabilityKernel); - ExecutionModeParams[ExecutionModeContractionOff].caps.push_back(CapabilityKernel); - - DecorationParams[DecorationRelaxedPrecision].caps.push_back(CapabilityShader); - DecorationParams[DecorationBlock].caps.push_back(CapabilityShader); - DecorationParams[DecorationBufferBlock].caps.push_back(CapabilityShader); - DecorationParams[DecorationRowMajor].caps.push_back(CapabilityMatrix); - DecorationParams[DecorationColMajor].caps.push_back(CapabilityMatrix); - DecorationParams[DecorationGLSLShared].caps.push_back(CapabilityShader); - DecorationParams[DecorationGLSLPacked].caps.push_back(CapabilityShader); - DecorationParams[DecorationNoPerspective].caps.push_back(CapabilityShader); - DecorationParams[DecorationFlat].caps.push_back(CapabilityShader); - DecorationParams[DecorationPatch].caps.push_back(CapabilityTessellation); - DecorationParams[DecorationCentroid].caps.push_back(CapabilityShader); - DecorationParams[DecorationSample].caps.push_back(CapabilitySampleRateShading); - DecorationParams[DecorationInvariant].caps.push_back(CapabilityShader); - DecorationParams[DecorationConstant].caps.push_back(CapabilityKernel); - DecorationParams[DecorationUniform].caps.push_back(CapabilityShader); - DecorationParams[DecorationCPacked].caps.push_back(CapabilityKernel); - DecorationParams[DecorationSaturatedConversion].caps.push_back(CapabilityKernel); - DecorationParams[DecorationStream].caps.push_back(CapabilityGeometryStreams); - DecorationParams[DecorationLocation].caps.push_back(CapabilityShader); - DecorationParams[DecorationComponent].caps.push_back(CapabilityShader); - DecorationParams[DecorationOffset].caps.push_back(CapabilityShader); - DecorationParams[DecorationIndex].caps.push_back(CapabilityShader); - DecorationParams[DecorationBinding].caps.push_back(CapabilityShader); - DecorationParams[DecorationDescriptorSet].caps.push_back(CapabilityShader); - DecorationParams[DecorationXfbBuffer].caps.push_back(CapabilityTransformFeedback); - DecorationParams[DecorationXfbStride].caps.push_back(CapabilityTransformFeedback); - DecorationParams[DecorationArrayStride].caps.push_back(CapabilityShader); - DecorationParams[DecorationMatrixStride].caps.push_back(CapabilityMatrix); - DecorationParams[DecorationFuncParamAttr].caps.push_back(CapabilityKernel); - DecorationParams[DecorationFPRoundingMode].caps.push_back(CapabilityKernel); - DecorationParams[DecorationFPFastMathMode].caps.push_back(CapabilityKernel); - DecorationParams[DecorationLinkageAttributes].caps.push_back(CapabilityLinkage); - DecorationParams[DecorationSpecId].caps.push_back(CapabilityShader); - DecorationParams[DecorationNoContraction].caps.push_back(CapabilityShader); - DecorationParams[DecorationInputAttachmentIndex].caps.push_back(CapabilityInputAttachment); - DecorationParams[DecorationAlignment].caps.push_back(CapabilityKernel); - - BuiltInParams[BuiltInPosition].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInPointSize].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInClipDistance].caps.push_back(CapabilityClipDistance); - BuiltInParams[BuiltInCullDistance].caps.push_back(CapabilityCullDistance); - - BuiltInParams[BuiltInVertexId].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInVertexId].desc = "Vertex ID, which takes on values 0, 1, 2, . . . ."; - - BuiltInParams[BuiltInInstanceId].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInInstanceId].desc = "Instance ID, which takes on values 0, 1, 2, . . . ."; - - BuiltInParams[BuiltInVertexIndex].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInVertexIndex].desc = "Vertex index, which takes on values base, base+1, base+2, . . . ."; - - BuiltInParams[BuiltInInstanceIndex].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInInstanceIndex].desc = "Instance index, which takes on values base, base+1, base+2, . . . ."; - - BuiltInParams[BuiltInPrimitiveId].caps.push_back(CapabilityGeometry); - BuiltInParams[BuiltInPrimitiveId].caps.push_back(CapabilityTessellation); - BuiltInParams[BuiltInInvocationId].caps.push_back(CapabilityGeometry); - BuiltInParams[BuiltInInvocationId].caps.push_back(CapabilityTessellation); - BuiltInParams[BuiltInLayer].caps.push_back(CapabilityGeometry); - BuiltInParams[BuiltInViewportIndex].caps.push_back(CapabilityMultiViewport); - BuiltInParams[BuiltInTessLevelOuter].caps.push_back(CapabilityTessellation); - BuiltInParams[BuiltInTessLevelInner].caps.push_back(CapabilityTessellation); - BuiltInParams[BuiltInTessCoord].caps.push_back(CapabilityTessellation); - BuiltInParams[BuiltInPatchVertices].caps.push_back(CapabilityTessellation); - BuiltInParams[BuiltInFragCoord].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInPointCoord].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInFrontFacing].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInSampleId].caps.push_back(CapabilitySampleRateShading); - BuiltInParams[BuiltInSamplePosition].caps.push_back(CapabilitySampleRateShading); - BuiltInParams[BuiltInSampleMask].caps.push_back(CapabilitySampleRateShading); - BuiltInParams[BuiltInFragDepth].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInHelperInvocation].caps.push_back(CapabilityShader); - BuiltInParams[BuiltInWorkDim].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInGlobalSize].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInEnqueuedWorkgroupSize].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInGlobalOffset].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInGlobalLinearId].caps.push_back(CapabilityKernel); - - BuiltInParams[BuiltInSubgroupSize].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInSubgroupMaxSize].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInNumSubgroups].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInNumEnqueuedSubgroups].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInSubgroupId].caps.push_back(CapabilityKernel); - BuiltInParams[BuiltInSubgroupLocalInvocationId].caps.push_back(CapabilityKernel); - - DimensionalityParams[Dim1D].caps.push_back(CapabilitySampled1D); - DimensionalityParams[DimCube].caps.push_back(CapabilityShader); - DimensionalityParams[DimRect].caps.push_back(CapabilitySampledRect); - DimensionalityParams[DimBuffer].caps.push_back(CapabilitySampledBuffer); - DimensionalityParams[DimSubpassData].caps.push_back(CapabilityInputAttachment); - - // Group Operations - for (int i = 0; i < GroupOperationCeiling; ++i) { - GroupOperationParams[i].caps.push_back(CapabilityKernel); - } - - // Enqueue flags - for (int i = 0; i < KernelEnqueueFlagsCeiling; ++i) { - KernelEnqueueFlagsParams[i].caps.push_back(CapabilityKernel); - } - - // Profiling info - KernelProfilingInfoParams[0].caps.push_back(CapabilityKernel); - - // set name of operator, an initial set of style operands, and the description - - InstructionDesc[OpSource].operands.push(OperandSource, ""); - InstructionDesc[OpSource].operands.push(OperandLiteralNumber, "'Version'"); - InstructionDesc[OpSource].operands.push(OperandId, "'File'", true); - InstructionDesc[OpSource].operands.push(OperandLiteralString, "'Source'", true); - - InstructionDesc[OpSourceContinued].operands.push(OperandLiteralString, "'Continued Source'"); - - InstructionDesc[OpSourceExtension].operands.push(OperandLiteralString, "'Extension'"); - - InstructionDesc[OpName].operands.push(OperandId, "'Target'"); - InstructionDesc[OpName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpMemberName].operands.push(OperandId, "'Type'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpString].operands.push(OperandLiteralString, "'String'"); - - InstructionDesc[OpLine].operands.push(OperandId, "'File'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Line'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Column'"); - - InstructionDesc[OpExtension].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpExtInstImport].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpCapability].operands.push(OperandCapability, "'Capability'"); - - InstructionDesc[OpMemoryModel].operands.push(OperandAddressing, ""); - InstructionDesc[OpMemoryModel].operands.push(OperandMemory, ""); - - InstructionDesc[OpEntryPoint].operands.push(OperandExecutionModel, ""); - InstructionDesc[OpEntryPoint].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpEntryPoint].operands.push(OperandLiteralString, "'Name'"); - InstructionDesc[OpEntryPoint].operands.push(OperandVariableIds, "'Interface'"); - - InstructionDesc[OpExecutionMode].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'"); - InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <>"); - - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'"); - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'"); - - InstructionDesc[OpTypeFloat].operands.push(OperandLiteralNumber, "'Width'"); - - InstructionDesc[OpTypeVector].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeVector].operands.push(OperandLiteralNumber, "'Component Count'"); - - InstructionDesc[OpTypeMatrix].capabilities.push_back(CapabilityMatrix); - InstructionDesc[OpTypeMatrix].operands.push(OperandId, "'Column Type'"); - InstructionDesc[OpTypeMatrix].operands.push(OperandLiteralNumber, "'Column Count'"); - - InstructionDesc[OpTypeImage].operands.push(OperandId, "'Sampled Type'"); - InstructionDesc[OpTypeImage].operands.push(OperandDimensionality, ""); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Depth'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Arrayed'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'MS'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Sampled'"); - InstructionDesc[OpTypeImage].operands.push(OperandSamplerImageFormat, ""); - InstructionDesc[OpTypeImage].operands.push(OperandAccessQualifier, "", true); - - InstructionDesc[OpTypeSampledImage].operands.push(OperandId, "'Image Type'"); - - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Element Type'"); - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Length'"); - - InstructionDesc[OpTypeRuntimeArray].capabilities.push_back(CapabilityShader); - InstructionDesc[OpTypeRuntimeArray].operands.push(OperandId, "'Element Type'"); - - InstructionDesc[OpTypeStruct].operands.push(OperandVariableIds, "'Member 0 type', +\n'member 1 type', +\n..."); - - InstructionDesc[OpTypeOpaque].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpTypeOpaque].operands.push(OperandLiteralString, "The name of the opaque type."); - - InstructionDesc[OpTypePointer].operands.push(OperandStorage, ""); - InstructionDesc[OpTypePointer].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpTypeForwardPointer].capabilities.push_back(CapabilityAddresses); - InstructionDesc[OpTypeForwardPointer].operands.push(OperandId, "'Pointer Type'"); - InstructionDesc[OpTypeForwardPointer].operands.push(OperandStorage, ""); - - InstructionDesc[OpTypeEvent].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpTypeDeviceEvent].capabilities.push_back(CapabilityDeviceEnqueue); - - InstructionDesc[OpTypeReserveId].capabilities.push_back(CapabilityPipes); - - InstructionDesc[OpTypeQueue].capabilities.push_back(CapabilityDeviceEnqueue); - - InstructionDesc[OpTypePipe].operands.push(OperandAccessQualifier, "'Qualifier'"); - InstructionDesc[OpTypePipe].capabilities.push_back(CapabilityPipes); - - InstructionDesc[OpTypeFunction].operands.push(OperandId, "'Return Type'"); - InstructionDesc[OpTypeFunction].operands.push(OperandVariableIds, "'Parameter 0 Type', +\n'Parameter 1 Type', +\n..."); - - InstructionDesc[OpConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpConstantSampler].capabilities.push_back(CapabilityLiteralSampler); - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerAddressingMode, ""); - InstructionDesc[OpConstantSampler].operands.push(OperandLiteralNumber, "'Param'"); - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerFilterMode, ""); - - InstructionDesc[OpSpecConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpSpecConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpSpecConstantOp].operands.push(OperandLiteralNumber, "'Opcode'"); - InstructionDesc[OpSpecConstantOp].operands.push(OperandVariableIds, "'Operands'"); - - InstructionDesc[OpVariable].operands.push(OperandStorage, ""); - InstructionDesc[OpVariable].operands.push(OperandId, "'Initializer'", true); - - InstructionDesc[OpFunction].operands.push(OperandFunction, ""); - InstructionDesc[OpFunction].operands.push(OperandId, "'Function Type'"); - - InstructionDesc[OpFunctionCall].operands.push(OperandId, "'Function'"); - InstructionDesc[OpFunctionCall].operands.push(OperandVariableIds, "'Argument 0', +\n'Argument 1', +\n..."); - - InstructionDesc[OpExtInst].operands.push(OperandId, "'Set'"); - InstructionDesc[OpExtInst].operands.push(OperandLiteralNumber, "'Instruction'"); - InstructionDesc[OpExtInst].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n..."); - - InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpStore].operands.push(OperandId, "'Object'"); - InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'"); - - InstructionDesc[OpDecorate].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'"); - - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandVariableIdLiteral, "'Targets'"); - - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Component'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 2'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandVariableLiterals, "'Components'"); - - InstructionDesc[OpCompositeConstruct].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpCompositeExtract].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeExtract].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCopyObject].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemory].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Size'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpCopyMemorySized].capabilities.push_back(CapabilityAddresses); - - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Image'"); - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Sampler'"); - - InstructionDesc[OpImage].operands.push(OperandId, "'Sampled Image'"); - - InstructionDesc[OpImageRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageRead].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Texel'"); - InstructionDesc[OpImageWrite].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageWrite].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSampleImplicitLod].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSampleDrefImplicitLod].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSampleDrefExplicitLod].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSampleProjImplicitLod].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSampleProjExplicitLod].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSampleProjDrefImplicitLod].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSampleProjDrefExplicitLod].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageFetch].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageGather].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageGather].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageDrefGather].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageDrefGather].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleImplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleExplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleProjImplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleProjExplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseFetch].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseFetch].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseGather].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseGather].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseDrefGather].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseRead].operands.push(OperandVariableIds, "", true); - InstructionDesc[OpImageSparseRead].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageSparseTexelsResident].operands.push(OperandId, "'Resident Code'"); - InstructionDesc[OpImageSparseTexelsResident].capabilities.push_back(CapabilitySparseResidency); - - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Level of Detail'"); - InstructionDesc[OpImageQuerySizeLod].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpImageQuerySizeLod].capabilities.push_back(CapabilityImageQuery); - - InstructionDesc[OpImageQuerySize].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQuerySize].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpImageQuerySize].capabilities.push_back(CapabilityImageQuery); - - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageQueryLod].capabilities.push_back(CapabilityImageQuery); - - InstructionDesc[OpImageQueryLevels].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQueryLevels].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpImageQueryLevels].capabilities.push_back(CapabilityImageQuery); - - InstructionDesc[OpImageQuerySamples].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQuerySamples].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpImageQuerySamples].capabilities.push_back(CapabilityImageQuery); - - InstructionDesc[OpImageQueryFormat].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQueryFormat].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpImageQueryOrder].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQueryOrder].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - InstructionDesc[OpPtrAccessChain].capabilities.push_back(CapabilityAddresses); - - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - InstructionDesc[OpInBoundsPtrAccessChain].capabilities.push_back(CapabilityAddresses); - - InstructionDesc[OpSNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpFNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpAny].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpAll].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpConvertFToU].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertFToS].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertSToF].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpConvertUToF].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpUConvert].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpSConvert].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpFConvert].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpSatConvertSToU].operands.push(OperandId, "'Signed Value'"); - InstructionDesc[OpSatConvertSToU].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpSatConvertUToS].operands.push(OperandId, "'Unsigned Value'"); - InstructionDesc[OpSatConvertUToS].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpConvertPtrToU].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpConvertPtrToU].capabilities.push_back(CapabilityAddresses); - - InstructionDesc[OpConvertUToPtr].operands.push(OperandId, "'Integer Value'"); - InstructionDesc[OpConvertUToPtr].capabilities.push_back(CapabilityAddresses); - - InstructionDesc[OpPtrCastToGeneric].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpPtrCastToGeneric].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpGenericCastToPtr].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpGenericCastToPtr].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandStorage, "'Storage'"); - InstructionDesc[OpGenericCastToPtrExplicit].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpGenericPtrMemSemantics].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpGenericPtrMemSemantics].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpBitcast].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpQuantizeToF16].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpTranspose].capabilities.push_back(CapabilityMatrix); - InstructionDesc[OpTranspose].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpIsNan].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsInf].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsFinite].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpIsFinite].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsNormal].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpIsNormal].operands.push(OperandId, "'x'"); - - InstructionDesc[OpSignBitSet].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpSignBitSet].operands.push(OperandId, "'x'"); - - InstructionDesc[OpLessOrGreater].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'x'"); - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'y'"); - - InstructionDesc[OpOrdered].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpOrdered].operands.push(OperandId, "'x'"); - InstructionDesc[OpOrdered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpUnordered].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpUnordered].operands.push(OperandId, "'x'"); - InstructionDesc[OpUnordered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpArrayLength].operands.push(OperandId, "'Structure'"); - InstructionDesc[OpArrayLength].operands.push(OperandLiteralNumber, "'Array member'"); - InstructionDesc[OpArrayLength].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpMatrixTimesScalar].capabilities.push_back(CapabilityMatrix); - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpVectorTimesMatrix].capabilities.push_back(CapabilityMatrix); - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpMatrixTimesVector].capabilities.push_back(CapabilityMatrix); - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpMatrixTimesMatrix].capabilities.push_back(CapabilityMatrix); - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'LeftMatrix'"); - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'RightMatrix'"); - - InstructionDesc[OpOuterProduct].capabilities.push_back(CapabilityMatrix); - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitFieldInsert].capabilities.push_back(CapabilityShader); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Insert'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldSExtract].capabilities.push_back(CapabilityShader); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldUExtract].capabilities.push_back(CapabilityShader); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitReverse].capabilities.push_back(CapabilityShader); - InstructionDesc[OpBitReverse].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpBitCount].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpSelect].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 1'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 2'"); - - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpDPdx].capabilities.push_back(CapabilityShader); - InstructionDesc[OpDPdx].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdy].capabilities.push_back(CapabilityShader); - InstructionDesc[OpDPdy].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidth].capabilities.push_back(CapabilityShader); - InstructionDesc[OpFwidth].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxFine].capabilities.push_back(CapabilityDerivativeControl); - InstructionDesc[OpDPdxFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyFine].capabilities.push_back(CapabilityDerivativeControl); - InstructionDesc[OpDPdyFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthFine].capabilities.push_back(CapabilityDerivativeControl); - InstructionDesc[OpFwidthFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxCoarse].capabilities.push_back(CapabilityDerivativeControl); - InstructionDesc[OpDPdxCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyCoarse].capabilities.push_back(CapabilityDerivativeControl); - InstructionDesc[OpDPdyCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthCoarse].capabilities.push_back(CapabilityDerivativeControl); - InstructionDesc[OpFwidthCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpEmitVertex].capabilities.push_back(CapabilityGeometry); - - InstructionDesc[OpEndPrimitive].capabilities.push_back(CapabilityGeometry); - - InstructionDesc[OpEmitStreamVertex].operands.push(OperandId, "'Stream'"); - InstructionDesc[OpEmitStreamVertex].capabilities.push_back(CapabilityGeometryStreams); - - InstructionDesc[OpEndStreamPrimitive].operands.push(OperandId, "'Stream'"); - InstructionDesc[OpEndStreamPrimitive].capabilities.push_back(CapabilityGeometryStreams); - - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpControlBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpMemoryBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpMemoryBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Sample'"); - - InstructionDesc[OpAtomicLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicStore].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicStore].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Comparator'"); - - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Comparator'"); - InstructionDesc[OpAtomicCompareExchangeWeak].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpAtomicIIncrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIDecrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicOr].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicOr].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicXor].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicXor].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFlagTestAndSet].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpAtomicFlagClear].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFlagClear].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'"); - InstructionDesc[OpLoopMerge].operands.push(OperandLoop, ""); - InstructionDesc[OpLoopMerge].operands.push(OperandOptionalLiteral, ""); - - InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpSelectionMerge].operands.push(OperandSelect, ""); - - InstructionDesc[OpBranch].operands.push(OperandId, "'Target Label'"); - - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'True Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'False Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandVariableLiterals, "'Branch weights'"); - - InstructionDesc[OpSwitch].operands.push(OperandId, "'Selector'"); - InstructionDesc[OpSwitch].operands.push(OperandId, "'Default'"); - InstructionDesc[OpSwitch].operands.push(OperandVariableLiteralId, "'Target'"); - - InstructionDesc[OpKill].capabilities.push_back(CapabilityShader); - - InstructionDesc[OpReturnValue].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpLifetimeStart].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStart].operands.push(OperandLiteralNumber, "'Size'"); - InstructionDesc[OpLifetimeStart].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpLifetimeStop].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStop].operands.push(OperandLiteralNumber, "'Size'"); - InstructionDesc[OpLifetimeStop].capabilities.push_back(CapabilityKernel); - - InstructionDesc[OpGroupAsyncCopy].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Destination'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Source'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Num Elements'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGroupWaitEvents].capabilities.push_back(CapabilityKernel); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Events List'"); - - InstructionDesc[OpGroupAll].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupAll].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAll].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupAny].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupAny].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAny].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupBroadcast].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'Value'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'LocalId'"); - - InstructionDesc[OpGroupIAdd].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupIAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAdd].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupFAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMin].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupUMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMin].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMin].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupSMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMin].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupFMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMax].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupUMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMax].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupSMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMax].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupFMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMax].operands.push(OperandId, "X"); - - InstructionDesc[OpReadPipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpWritePipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedReadPipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedWritePipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveReadPipePackets].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveWritePipePackets].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitReadPipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitWritePipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpIsValidReserveId].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpIsValidReserveId].operands.push(OperandId, "'Reserve Id'"); - - InstructionDesc[OpGetNumPipePackets].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGetMaxPipePackets].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveReadPipePackets].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveWritePipePackets].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitReadPipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitWritePipe].capabilities.push_back(CapabilityPipes); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpBuildNDRange].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'LocalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkOffset'"); - - InstructionDesc[OpGetDefaultQueue].capabilities.push_back(CapabilityDeviceEnqueue); - - InstructionDesc[OpCaptureEventProfilingInfo].capabilities.push_back(CapabilityDeviceEnqueue); - - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Event'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Profiling Info'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSetUserEventStatus].capabilities.push_back(CapabilityDeviceEnqueue); - - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Event'"); - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Status'"); - - InstructionDesc[OpIsValidEvent].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpIsValidEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpCreateUserEvent].capabilities.push_back(CapabilityDeviceEnqueue); - - InstructionDesc[OpRetainEvent].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpRetainEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpReleaseEvent].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpReleaseEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGetKernelWorkGroupSize].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeSubGroupCount].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpEnqueueKernel].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Flags'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Ret Event'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Align'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandVariableIds, "'Local Size'"); - - InstructionDesc[OpEnqueueMarker].capabilities.push_back(CapabilityDeviceEnqueue); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Ret Event'"); - - InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupFirstInvocationKHR].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSubgroupAnyKHR].capabilities.push_back(CapabilitySubgroupVoteKHR); - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllKHR].capabilities.push_back(CapabilitySubgroupVoteKHR); - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllEqualKHR].capabilities.push_back(CapabilitySubgroupVoteKHR); - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupReadInvocationKHR].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'"); - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'"); - -#ifdef AMD_EXTENSIONS - InstructionDesc[OpGroupIAddNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAddNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMinNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMinNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMinNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMaxNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMaxNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMaxNonUniformAMD].capabilities.push_back(CapabilityGroups); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpFragmentMaskFetchAMD].capabilities.push_back(CapabilityFragmentMaskAMD); - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Coordinate'"); - - InstructionDesc[OpFragmentFetchAMD].capabilities.push_back(CapabilityFragmentMaskAMD); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Fragment Index'"); -#endif -} - -}; // end spv namespace diff --git a/third_party/glslang-spirv/doc.h b/third_party/glslang-spirv/doc.h deleted file mode 100644 index 710ca1a52..000000000 --- a/third_party/glslang-spirv/doc.h +++ /dev/null @@ -1,262 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Parameterize the SPIR-V enumerants. -// - -#pragma once - -#include "spirv.hpp" - -#include - -namespace spv { - -// Fill in all the parameters -void Parameterize(); - -// Return the English names of all the enums. -const char* SourceString(int); -const char* AddressingString(int); -const char* MemoryString(int); -const char* ExecutionModelString(int); -const char* ExecutionModeString(int); -const char* StorageClassString(int); -const char* DecorationString(int); -const char* BuiltInString(int); -const char* DimensionString(int); -const char* SelectControlString(int); -const char* LoopControlString(int); -const char* FunctionControlString(int); -const char* SamplerAddressingModeString(int); -const char* SamplerFilterModeString(int); -const char* ImageFormatString(int); -const char* ImageChannelOrderString(int); -const char* ImageChannelTypeString(int); -const char* ImageChannelDataTypeString(int type); -const char* ImageOperandsString(int format); -const char* ImageOperands(int); -const char* FPFastMathString(int); -const char* FPRoundingModeString(int); -const char* LinkageTypeString(int); -const char* FuncParamAttrString(int); -const char* AccessQualifierString(int); -const char* MemorySemanticsString(int); -const char* MemoryAccessString(int); -const char* ExecutionScopeString(int); -const char* GroupOperationString(int); -const char* KernelEnqueueFlagsString(int); -const char* KernelProfilingInfoString(int); -const char* CapabilityString(int); -const char* OpcodeString(int); -const char* ScopeString(int mem); - -// For grouping opcodes into subsections -enum OpcodeClass { - OpClassMisc, - OpClassDebug, - OpClassAnnotate, - OpClassExtension, - OpClassMode, - OpClassType, - OpClassConstant, - OpClassMemory, - OpClassFunction, - OpClassImage, - OpClassConvert, - OpClassComposite, - OpClassArithmetic, - OpClassBit, - OpClassRelationalLogical, - OpClassDerivative, - OpClassFlowControl, - OpClassAtomic, - OpClassPrimitive, - OpClassBarrier, - OpClassGroup, - OpClassDeviceSideEnqueue, - OpClassPipe, - - OpClassCount, - OpClassMissing // all instructions start out as missing -}; - -// For parameterizing operands. -enum OperandClass { - OperandNone, - OperandId, - OperandVariableIds, - OperandOptionalLiteral, - OperandOptionalLiteralString, - OperandVariableLiterals, - OperandVariableIdLiteral, - OperandVariableLiteralId, - OperandLiteralNumber, - OperandLiteralString, - 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) { } - EnumCaps caps; - 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; - EnumCaps capabilities; - OpcodeClass opClass; - OperandParameters operands; - -protected: - int typePresent : 1; - int resultPresent : 1; -}; - -const int OpcodeCeiling = 321; - -// 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/third_party/glslang-spirv/hex_float.h b/third_party/glslang-spirv/hex_float.h deleted file mode 100644 index 905b21a45..000000000 --- a/third_party/glslang-spirv/hex_float.h +++ /dev/null @@ -1,1078 +0,0 @@ -// Copyright (c) 2015-2016 The Khronos Group Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_ -#define LIBSPIRV_UTIL_HEX_FLOAT_H_ - -#include -#include -#include -#include -#include -#include -#include - -#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/third_party/glslang-spirv/spirv.hpp b/third_party/glslang-spirv/spirv.hpp deleted file mode 100644 index c6776638e..000000000 --- a/third_party/glslang-spirv/spirv.hpp +++ /dev/null @@ -1,1028 +0,0 @@ -// Copyright (c) 2014-2018 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and/or associated documentation files (the "Materials"), -// to deal in the Materials without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Materials, and to permit persons to whom the -// Materials are furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -// IN THE MATERIALS. - -// 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 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'] -// -// 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 0x10200 -#define SPV_REVISION 3 - -static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010200; -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, - ExecutionModelMax = 0x7fffffff, -}; - -enum AddressingModel { - AddressingModelLogical = 0, - AddressingModelPhysical32 = 1, - AddressingModelPhysical64 = 2, - AddressingModelMax = 0x7fffffff, -}; - -enum MemoryModel { - MemoryModelSimple = 0, - MemoryModelGLSL450 = 1, - MemoryModelOpenCL = 2, - 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, - ExecutionModeStencilRefReplacingEXT = 5027, - 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, - 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, - ImageOperandsMax = 0x7fffffff, -}; - -enum ImageOperandsMask { - ImageOperandsMaskNone = 0, - ImageOperandsBiasMask = 0x00000001, - ImageOperandsLodMask = 0x00000002, - ImageOperandsGradMask = 0x00000004, - ImageOperandsConstOffsetMask = 0x00000008, - ImageOperandsOffsetMask = 0x00000010, - ImageOperandsConstOffsetsMask = 0x00000020, - ImageOperandsSampleMask = 0x00000040, - ImageOperandsMinLodMask = 0x00000080, -}; - -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, - 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, - DecorationExplicitInterpAMD = 4999, - DecorationOverrideCoverageNV = 5248, - DecorationPassthroughNV = 5250, - DecorationViewportRelativeNV = 5252, - DecorationSecondaryViewportRelativeNV = 5256, - 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, - BuiltInSubgroupEqMaskKHR = 4416, - BuiltInSubgroupGeMaskKHR = 4417, - BuiltInSubgroupGtMaskKHR = 4418, - BuiltInSubgroupLeMaskKHR = 4419, - 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, - 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, - LoopControlMax = 0x7fffffff, -}; - -enum LoopControlMask { - LoopControlMaskNone = 0, - LoopControlUnrollMask = 0x00000001, - LoopControlDontUnrollMask = 0x00000002, - LoopControlDependencyInfiniteMask = 0x00000004, - LoopControlDependencyLengthMask = 0x00000008, -}; - -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, - 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, -}; - -enum MemoryAccessShift { - MemoryAccessVolatileShift = 0, - MemoryAccessAlignedShift = 1, - MemoryAccessNontemporalShift = 2, - MemoryAccessMax = 0x7fffffff, -}; - -enum MemoryAccessMask { - MemoryAccessMaskNone = 0, - MemoryAccessVolatileMask = 0x00000001, - MemoryAccessAlignedMask = 0x00000002, - MemoryAccessNontemporalMask = 0x00000004, -}; - -enum Scope { - ScopeCrossDevice = 0, - ScopeDevice = 1, - ScopeWorkgroup = 2, - ScopeSubgroup = 3, - ScopeInvocation = 4, - ScopeMax = 0x7fffffff, -}; - -enum GroupOperation { - GroupOperationReduce = 0, - GroupOperationInclusiveScan = 1, - GroupOperationExclusiveScan = 2, - 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, - 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, - CapabilityImageGatherBiasLodAMD = 5009, - CapabilityFragmentMaskAMD = 5010, - CapabilityStencilExportEXT = 5013, - CapabilityImageReadWriteLodAMD = 5015, - CapabilitySampleMaskOverrideCoverageNV = 5249, - CapabilityGeometryShaderPassthroughNV = 5251, - CapabilityShaderViewportIndexLayerEXT = 5254, - CapabilityShaderViewportIndexLayerNV = 5254, - CapabilityShaderViewportMaskNV = 5255, - CapabilityShaderStereoViewNV = 5259, - CapabilityPerViewAttributesNV = 5260, - CapabilityFragmentFullyCoveredEXT = 5265, - CapabilitySubgroupShuffleINTEL = 5568, - CapabilitySubgroupBufferBlockIOINTEL = 5569, - CapabilitySubgroupImageBlockIOINTEL = 5570, - CapabilityMax = 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, - OpSubgroupBallotKHR = 4421, - OpSubgroupFirstInvocationKHR = 4422, - OpSubgroupAllKHR = 4428, - OpSubgroupAnyKHR = 4429, - OpSubgroupAllEqualKHR = 4430, - OpSubgroupReadInvocationKHR = 4432, - OpGroupIAddNonUniformAMD = 5000, - OpGroupFAddNonUniformAMD = 5001, - OpGroupFMinNonUniformAMD = 5002, - OpGroupUMinNonUniformAMD = 5003, - OpGroupSMinNonUniformAMD = 5004, - OpGroupFMaxNonUniformAMD = 5005, - OpGroupUMaxNonUniformAMD = 5006, - OpGroupSMaxNonUniformAMD = 5007, - OpFragmentMaskFetchAMD = 5011, - OpFragmentFetchAMD = 5012, - OpSubgroupShuffleINTEL = 5571, - OpSubgroupShuffleDownINTEL = 5572, - OpSubgroupShuffleUpINTEL = 5573, - OpSubgroupShuffleXorINTEL = 5574, - OpSubgroupBlockReadINTEL = 5575, - OpSubgroupBlockWriteINTEL = 5576, - OpSubgroupImageBlockReadINTEL = 5577, - OpSubgroupImageBlockWriteINTEL = 5578, - OpMax = 0x7fffffff, -}; - -// 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)); } - -} // end namespace spv - -#endif // #ifndef spirv_HPP - diff --git a/third_party/glslang-spirv/spvIR.h b/third_party/glslang-spirv/spvIR.h deleted file mode 100644 index faa2701ff..000000000 --- a/third_party/glslang-spirv/spvIR.h +++ /dev/null @@ -1,407 +0,0 @@ -// -// Copyright (C) 2014 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. - -// 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); - -// -// 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); } - void addImmediateOperand(unsigned int immediate) { operands.push_back(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); - } - } - void setBlock(Block* b) { block = b; } - Block* getBlock() const { return block; } - Op getOpCode() const { return opCode; } - int getNumOperands() const { return (int)operands.size(); } - Id getResultId() const { return resultId; } - Id getTypeId() const { return typeId; } - Id getIdOperand(int op) const { return operands[op]; } - unsigned int getImmediateOperand(int op) const { 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; - 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; - } - 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; - } - - bool isTerminated() const - { - switch (instructions.back()->getOpCode()) { - case OpBranch: - case OpBranchConditional: - case OpSwitch: - case OpKill: - case OpReturn: - case OpReturnValue: - 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; -}; - -// 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. -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) { return parameterInstructions[p]->getResultId(); } - - 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) { 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]->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/third_party/spirv-headers b/third_party/spirv-headers deleted file mode 160000 index 2bf91d32b..000000000 --- a/third_party/spirv-headers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2bf91d32b2ce17df9ca6c1e62cf478b24e7d2644 diff --git a/third_party/spirv-tools b/third_party/spirv-tools deleted file mode 160000 index 27a2bbb86..000000000 --- a/third_party/spirv-tools +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 27a2bbb865ef638afe4260bf214110425a2b904b diff --git a/third_party/spirv-tools.lua b/third_party/spirv-tools.lua deleted file mode 100644 index bf900a6e9..000000000 --- a/third_party/spirv-tools.lua +++ /dev/null @@ -1,76 +0,0 @@ -group("third_party") -project("spirv-tools") - uuid("621512da-bb50-40f2-85ba-ae615ff13e68") - kind("StaticLib") - language("C++") - links({ - }) - defines({ - "_LIB", - }) - includedirs({ - "spirv-headers/include", - "spirv-tools/include", - "spirv-tools/source", - }) - files({ - "spirv-tools/include/spirv-tools/libspirv.h", - "spirv-tools/source/val/basic_block.cpp", - "spirv-tools/source/val/basic_block.h", - "spirv-tools/source/val/construct.cpp", - "spirv-tools/source/val/construct.h", - "spirv-tools/source/val/function.cpp", - "spirv-tools/source/val/function.h", - "spirv-tools/source/val/validation_state.cpp", - "spirv-tools/source/val/validation_state.h", - "spirv-tools/source/util/*.cpp", - "spirv-tools/source/util/*.h", - "spirv-tools/source/val/*.cpp", - "spirv-tools/source/val/*.h", - "spirv-tools/source/*.inc", - "spirv-tools/source/*.cpp", - "spirv-tools/source/*.h", - "spirv-tools/source/assembly_grammar.cpp", - "spirv-tools/source/assembly_grammar.h", - "spirv-tools/source/binary.cpp", - "spirv-tools/source/binary.h", - "spirv-tools/source/diagnostic.cpp", - "spirv-tools/source/diagnostic.h", - "spirv-tools/source/disassemble.cpp", - "spirv-tools/source/ext_inst.cpp", - "spirv-tools/source/ext_inst.h", - "spirv-tools/source/instruction.h", - "spirv-tools/source/macro.h", - "spirv-tools/source/opcode.cpp", - "spirv-tools/source/opcode.h", - "spirv-tools/source/operand.cpp", - "spirv-tools/source/operand.h", - "spirv-tools/source/print.cpp", - "spirv-tools/source/print.h", - -- "spirv-tools/source/software_version.cpp", - "spirv-tools/source/spirv_constant.h", - "spirv-tools/source/spirv_definition.h", - "spirv-tools/source/spirv_endian.cpp", - "spirv-tools/source/spirv_endian.h", - "spirv-tools/source/spirv_target_env.cpp", - "spirv-tools/source/spirv_target_env.h", - "spirv-tools/source/table.cpp", - "spirv-tools/source/table.h", - "spirv-tools/source/text.cpp", - "spirv-tools/source/text.h", - "spirv-tools/source/text_handler.cpp", - "spirv-tools/source/text_handler.h", - "spirv-tools/source/validate.cpp", - "spirv-tools/source/validate.h", - "spirv-tools/source/validate_cfg.cpp", - "spirv-tools/source/validate_id.cpp", - "spirv-tools/source/validate_instruction.cpp", - "spirv-tools/source/validate_layout.cpp", - "spirv-tools/source/util/bitutils.h", - "spirv-tools/source/util/hex_float.h", - }) - filter("platforms:Windows") - buildoptions({ - "/wd4800", -- Forcing value to bool 'true' or 'false' - "/wd4996", -- Call to 'std::equal' with parameters that may be unsafe - }) \ No newline at end of file diff --git a/third_party/spirv/GLSL.std.450.h b/third_party/spirv/GLSL.std.450.h deleted file mode 100644 index df31092be..000000000 --- a/third_party/spirv/GLSL.std.450.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLstd450_H -#define GLSLstd450_H - -static const int GLSLstd450Version = 100; -static const int GLSLstd450Revision = 1; - -enum GLSLstd450 { - GLSLstd450Bad = 0, // Don't use - - GLSLstd450Round = 1, - GLSLstd450RoundEven = 2, - GLSLstd450Trunc = 3, - GLSLstd450FAbs = 4, - GLSLstd450SAbs = 5, - GLSLstd450FSign = 6, - GLSLstd450SSign = 7, - GLSLstd450Floor = 8, - GLSLstd450Ceil = 9, - GLSLstd450Fract = 10, - - GLSLstd450Radians = 11, - GLSLstd450Degrees = 12, - GLSLstd450Sin = 13, - GLSLstd450Cos = 14, - GLSLstd450Tan = 15, - GLSLstd450Asin = 16, - GLSLstd450Acos = 17, - GLSLstd450Atan = 18, - GLSLstd450Sinh = 19, - GLSLstd450Cosh = 20, - GLSLstd450Tanh = 21, - GLSLstd450Asinh = 22, - GLSLstd450Acosh = 23, - GLSLstd450Atanh = 24, - GLSLstd450Atan2 = 25, - - GLSLstd450Pow = 26, - GLSLstd450Exp = 27, - GLSLstd450Log = 28, - GLSLstd450Exp2 = 29, - GLSLstd450Log2 = 30, - GLSLstd450Sqrt = 31, - GLSLstd450InverseSqrt = 32, - - GLSLstd450Determinant = 33, - GLSLstd450MatrixInverse = 34, - - GLSLstd450Modf = 35, // second operand needs an OpVariable to write to - GLSLstd450ModfStruct = 36, // no OpVariable operand - GLSLstd450FMin = 37, - GLSLstd450UMin = 38, - GLSLstd450SMin = 39, - GLSLstd450FMax = 40, - GLSLstd450UMax = 41, - GLSLstd450SMax = 42, - GLSLstd450FClamp = 43, - GLSLstd450UClamp = 44, - GLSLstd450SClamp = 45, - GLSLstd450FMix = 46, - GLSLstd450IMix = 47, // Reserved - GLSLstd450Step = 48, - GLSLstd450SmoothStep = 49, - - GLSLstd450Fma = 50, - GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to - GLSLstd450FrexpStruct = 52, // no OpVariable operand - GLSLstd450Ldexp = 53, - - GLSLstd450PackSnorm4x8 = 54, - GLSLstd450PackUnorm4x8 = 55, - GLSLstd450PackSnorm2x16 = 56, - GLSLstd450PackUnorm2x16 = 57, - GLSLstd450PackHalf2x16 = 58, - GLSLstd450PackDouble2x32 = 59, - GLSLstd450UnpackSnorm2x16 = 60, - GLSLstd450UnpackUnorm2x16 = 61, - GLSLstd450UnpackHalf2x16 = 62, - GLSLstd450UnpackSnorm4x8 = 63, - GLSLstd450UnpackUnorm4x8 = 64, - GLSLstd450UnpackDouble2x32 = 65, - - GLSLstd450Length = 66, - GLSLstd450Distance = 67, - GLSLstd450Cross = 68, - GLSLstd450Normalize = 69, - GLSLstd450FaceForward = 70, - GLSLstd450Reflect = 71, - GLSLstd450Refract = 72, - - GLSLstd450FindILsb = 73, - GLSLstd450FindSMsb = 74, - GLSLstd450FindUMsb = 75, - - GLSLstd450InterpolateAtCentroid = 76, - GLSLstd450InterpolateAtSample = 77, - GLSLstd450InterpolateAtOffset = 78, - - GLSLstd450NMin = 79, - GLSLstd450NMax = 80, - GLSLstd450NClamp = 81, - - GLSLstd450Count -}; - -#endif // #ifndef GLSLstd450_H diff --git a/third_party/spirv/GLSL.std.450.hpp11 b/third_party/spirv/GLSL.std.450.hpp11 deleted file mode 100644 index 526912006..000000000 --- a/third_party/spirv/GLSL.std.450.hpp11 +++ /dev/null @@ -1,135 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLstd450_HPP -#define GLSLstd450_HPP - -namespace spv { - -constexpr int GLSLstd450Version = 100; -constexpr int GLSLstd450Revision = 1; - -enum class GLSLstd450 { - kBad = 0, // Don't use - - kRound = 1, - kRoundEven = 2, - kTrunc = 3, - kFAbs = 4, - kSAbs = 5, - kFSign = 6, - kSSign = 7, - kFloor = 8, - kCeil = 9, - kFract = 10, - - kRadians = 11, - kDegrees = 12, - kSin = 13, - kCos = 14, - kTan = 15, - kAsin = 16, - kAcos = 17, - kAtan = 18, - kSinh = 19, - kCosh = 20, - kTanh = 21, - kAsinh = 22, - kAcosh = 23, - kAtanh = 24, - kAtan2 = 25, - - kPow = 26, - kExp = 27, - kLog = 28, - kExp2 = 29, - kLog2 = 30, - kSqrt = 31, - kInverseSqrt = 32, - - kDeterminant = 33, - kMatrixInverse = 34, - - kModf = 35, // second operand needs an OpVariable to write to - kModfStruct = 36, // no OpVariable operand - kFMin = 37, - kUMin = 38, - kSMin = 39, - kFMax = 40, - kUMax = 41, - kSMax = 42, - kFClamp = 43, - kUClamp = 44, - kSClamp = 45, - kFMix = 46, - kIMix = 47, // Reserved - kStep = 48, - kSmoothStep = 49, - - kFma = 50, - kFrexp = 51, // second operand needs an OpVariable to write to - kFrexpStruct = 52, // no OpVariable operand - kLdexp = 53, - - kPackSnorm4x8 = 54, - kPackUnorm4x8 = 55, - kPackSnorm2x16 = 56, - kPackUnorm2x16 = 57, - kPackHalf2x16 = 58, - kPackDouble2x32 = 59, - kUnpackSnorm2x16 = 60, - kUnpackUnorm2x16 = 61, - kUnpackHalf2x16 = 62, - kUnpackSnorm4x8 = 63, - kUnpackUnorm4x8 = 64, - kUnpackDouble2x32 = 65, - - kLength = 66, - kDistance = 67, - kCross = 68, - kNormalize = 69, - kFaceForward = 70, - kReflect = 71, - kRefract = 72, - - kFindILsb = 73, - kFindSMsb = 74, - kFindUMsb = 75, - - kInterpolateAtCentroid = 76, - kInterpolateAtSample = 77, - kInterpolateAtOffset = 78, - - kNMin = 79, - kNMax = 80, - kNClamp = 81, - - kCount -}; - -} // namespace spv - -#endif // #ifndef GLSLstd450_HPP diff --git a/third_party/spirv/OpenCL.std.h b/third_party/spirv/OpenCL.std.h deleted file mode 100644 index af29c527e..000000000 --- a/third_party/spirv/OpenCL.std.h +++ /dev/null @@ -1,272 +0,0 @@ -/* -** Copyright (c) 2015-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. -*/ - -// -// Author: Boaz Ouriel, Intel -// - -namespace OpenCLLIB { - -enum Entrypoints { - - // math functions - Acos = 0, - Acosh = 1, - Acospi = 2, - Asin = 3, - Asinh = 4, - Asinpi = 5, - Atan = 6, - Atan2 = 7, - Atanh = 8, - Atanpi = 9, - Atan2pi = 10, - Cbrt = 11, - Ceil = 12, - Copysign = 13, - Cos = 14, - Cosh = 15, - Cospi = 16, - Erfc = 17, - Erf = 18, - Exp = 19, - Exp2 = 20, - Exp10 = 21, - Expm1 = 22, - Fabs = 23, - Fdim = 24, - Floor = 25, - Fma = 26, - Fmax = 27, - Fmin = 28, - Fmod = 29, - Fract = 30, - Frexp = 31, - Hypot = 32, - Ilogb = 33, - Ldexp = 34, - Lgamma = 35, - Lgamma_r = 36, - Log = 37, - Log2 = 38, - Log10 = 39, - Log1p = 40, - Logb = 41, - Mad = 42, - Maxmag = 43, - Minmag = 44, - Modf = 45, - Nan = 46, - Nextafter = 47, - Pow = 48, - Pown = 49, - Powr = 50, - Remainder = 51, - Remquo = 52, - Rint = 53, - Rootn = 54, - Round = 55, - Rsqrt = 56, - Sin = 57, - Sincos = 58, - Sinh = 59, - Sinpi = 60, - Sqrt = 61, - Tan = 62, - Tanh = 63, - Tanpi = 64, - Tgamma = 65, - Trunc = 66, - Half_cos = 67, - Half_divide = 68, - Half_exp = 69, - Half_exp2 = 70, - Half_exp10 = 71, - Half_log = 72, - Half_log2 = 73, - Half_log10 = 74, - Half_powr = 75, - Half_recip = 76, - Half_rsqrt = 77, - Half_sin = 78, - Half_sqrt = 79, - Half_tan = 80, - Native_cos = 81, - Native_divide = 82, - Native_exp = 83, - Native_exp2 = 84, - Native_exp10 = 85, - Native_log = 86, - Native_log2 = 87, - Native_log10 = 88, - Native_powr = 89, - Native_recip = 90, - Native_rsqrt = 91, - Native_sin = 92, - Native_sqrt = 93, - Native_tan = 94, - - // Common - FClamp = 95, - Degrees = 96, - FMax_common = 97, - FMin_common = 98, - Mix = 99, - Radians = 100, - Step = 101, - Smoothstep = 102, - Sign = 103, - - // Geometrics - Cross = 104, - Distance = 105, - Length = 106, - Normalize = 107, - Fast_distance = 108, - Fast_length = 109, - Fast_normalize = 110, - - // Images - Deprecated - Read_imagef = 111, - Read_imagei = 112, - Read_imageui = 113, - Read_imageh = 114, - - Read_imagef_samplerless = 115, - Read_imagei_samplerless = 116, - Read_imageui_samplerless = 117, - Read_imageh_samplerless = 118, - - Write_imagef = 119, - Write_imagei = 120, - Write_imageui = 121, - Write_imageh = 122, - Read_imagef_mipmap_lod = 123, - Read_imagei_mipmap_lod = 124, - Read_imageui_mipmap_lod = 125, - Read_imagef_mipmap_grad = 126, - Read_imagei_mipmap_grad = 127, - Read_imageui_mipmap_grad = 128, - - // Image write with LOD - Write_imagef_mipmap_lod = 129, - Write_imagei_mipmap_lod = 130, - Write_imageui_mipmap_lod = 131, - - // Images - Deprecated - Get_image_width = 132, - Get_image_height = 133, - Get_image_depth = 134, - Get_image_channel_data_type = 135, - Get_image_channel_order = 136, - Get_image_dim = 137, - Get_image_array_size = 138, - Get_image_num_samples = 139, - Get_image_num_mip_levels = 140, - - // Integers - SAbs = 141, - SAbs_diff = 142, - SAdd_sat = 143, - UAdd_sat = 144, - SHadd = 145, - UHadd = 146, - SRhadd = 147, - URhadd = 148, - SClamp = 149, - UClamp = 150, - Clz = 151, - Ctz = 152, - SMad_hi = 153, - UMad_sat = 154, - SMad_sat = 155, - SMax = 156, - UMax = 157, - SMin = 158, - UMin = 159, - SMul_hi = 160, - Rotate = 161, - SSub_sat = 162, - USub_sat = 163, - U_Upsample = 164, - S_Upsample = 165, - Popcount = 166, - SMad24 = 167, - UMad24 = 168, - SMul24 = 169, - UMul24 = 170, - - // Vector Loads/Stores - Vloadn = 171, - Vstoren = 172, - Vload_half = 173, - Vload_halfn = 174, - Vstore_half = 175, - Vstore_half_r = 176, - Vstore_halfn = 177, - Vstore_halfn_r = 178, - Vloada_halfn = 179, - Vstorea_halfn = 180, - Vstorea_halfn_r = 181, - - // Vector Misc - Shuffle = 182, - Shuffle2 = 183, - - // - Printf = 184, - Prefetch = 185, - - // Relationals - Bitselect = 186, - Select = 187, - - // pipes - Read_pipe = 188, - Write_pipe = 189, - Reserve_read_pipe = 190, - Reserve_write_pipe = 191, - Commit_read_pipe = 192, - Commit_write_pipe = 193, - Is_valid_reserve_id = 194, - Work_group_reserve_read_pipe = 195, - Work_group_reserve_write_pipe = 196, - Work_group_commit_read_pipe = 197, - Work_group_commit_write_pipe = 198, - Get_pipe_num_packets = 199, - Get_pipe_max_packets = 200, - - // more integers - UAbs = 201, - UAbs_diff = 202, - UMul_hi = 203, - UMad_hi = 204, -}; - - - -}; // end namespace OpenCL20 - diff --git a/third_party/spirv/spirv.h b/third_party/spirv/spirv.h deleted file mode 100644 index d48488e94..000000000 --- a/third_party/spirv/spirv.h +++ /dev/null @@ -1,871 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -/* -** 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 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'] -** -** 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 0x10000 -#define SPV_REVISION 3 - -static const unsigned int SpvMagicNumber = 0x07230203; -static const unsigned int SpvVersion = 0x00010000; -static const unsigned int SpvRevision = 3; -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, -} SpvSourceLanguage; - -typedef enum SpvExecutionModel_ { - SpvExecutionModelVertex = 0, - SpvExecutionModelTessellationControl = 1, - SpvExecutionModelTessellationEvaluation = 2, - SpvExecutionModelGeometry = 3, - SpvExecutionModelFragment = 4, - SpvExecutionModelGLCompute = 5, - SpvExecutionModelKernel = 6, -} SpvExecutionModel; - -typedef enum SpvAddressingModel_ { - SpvAddressingModelLogical = 0, - SpvAddressingModelPhysical32 = 1, - SpvAddressingModelPhysical64 = 2, -} SpvAddressingModel; - -typedef enum SpvMemoryModel_ { - SpvMemoryModelSimple = 0, - SpvMemoryModelGLSL450 = 1, - SpvMemoryModelOpenCL = 2, -} 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, -} 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, -} SpvStorageClass; - -typedef enum SpvDim_ { - SpvDim1D = 0, - SpvDim2D = 1, - SpvDim3D = 2, - SpvDimCube = 3, - SpvDimRect = 4, - SpvDimBuffer = 5, - SpvDimSubpassData = 6, -} SpvDim; - -typedef enum SpvSamplerAddressingMode_ { - SpvSamplerAddressingModeNone = 0, - SpvSamplerAddressingModeClampToEdge = 1, - SpvSamplerAddressingModeClamp = 2, - SpvSamplerAddressingModeRepeat = 3, - SpvSamplerAddressingModeRepeatMirrored = 4, -} SpvSamplerAddressingMode; - -typedef enum SpvSamplerFilterMode_ { - SpvSamplerFilterModeNearest = 0, - SpvSamplerFilterModeLinear = 1, -} 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, -} 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, -} 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, -} SpvImageChannelDataType; - -typedef enum SpvImageOperandsShift_ { - SpvImageOperandsBiasShift = 0, - SpvImageOperandsLodShift = 1, - SpvImageOperandsGradShift = 2, - SpvImageOperandsConstOffsetShift = 3, - SpvImageOperandsOffsetShift = 4, - SpvImageOperandsConstOffsetsShift = 5, - SpvImageOperandsSampleShift = 6, - SpvImageOperandsMinLodShift = 7, -} SpvImageOperandsShift; - -typedef enum SpvImageOperandsMask_ { - SpvImageOperandsMaskNone = 0, - SpvImageOperandsBiasMask = 0x00000001, - SpvImageOperandsLodMask = 0x00000002, - SpvImageOperandsGradMask = 0x00000004, - SpvImageOperandsConstOffsetMask = 0x00000008, - SpvImageOperandsOffsetMask = 0x00000010, - SpvImageOperandsConstOffsetsMask = 0x00000020, - SpvImageOperandsSampleMask = 0x00000040, - SpvImageOperandsMinLodMask = 0x00000080, -} SpvImageOperandsMask; - -typedef enum SpvFPFastMathModeShift_ { - SpvFPFastMathModeNotNaNShift = 0, - SpvFPFastMathModeNotInfShift = 1, - SpvFPFastMathModeNSZShift = 2, - SpvFPFastMathModeAllowRecipShift = 3, - SpvFPFastMathModeFastShift = 4, -} 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, -} SpvFPRoundingMode; - -typedef enum SpvLinkageType_ { - SpvLinkageTypeExport = 0, - SpvLinkageTypeImport = 1, -} SpvLinkageType; - -typedef enum SpvAccessQualifier_ { - SpvAccessQualifierReadOnly = 0, - SpvAccessQualifierWriteOnly = 1, - SpvAccessQualifierReadWrite = 2, -} SpvAccessQualifier; - -typedef enum SpvFunctionParameterAttribute_ { - SpvFunctionParameterAttributeZext = 0, - SpvFunctionParameterAttributeSext = 1, - SpvFunctionParameterAttributeByVal = 2, - SpvFunctionParameterAttributeSret = 3, - SpvFunctionParameterAttributeNoAlias = 4, - SpvFunctionParameterAttributeNoCapture = 5, - SpvFunctionParameterAttributeNoWrite = 6, - SpvFunctionParameterAttributeNoReadWrite = 7, -} 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, - 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, -} 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, -} SpvBuiltIn; - -typedef enum SpvSelectionControlShift_ { - SpvSelectionControlFlattenShift = 0, - SpvSelectionControlDontFlattenShift = 1, -} SpvSelectionControlShift; - -typedef enum SpvSelectionControlMask_ { - SpvSelectionControlMaskNone = 0, - SpvSelectionControlFlattenMask = 0x00000001, - SpvSelectionControlDontFlattenMask = 0x00000002, -} SpvSelectionControlMask; - -typedef enum SpvLoopControlShift_ { - SpvLoopControlUnrollShift = 0, - SpvLoopControlDontUnrollShift = 1, -} SpvLoopControlShift; - -typedef enum SpvLoopControlMask_ { - SpvLoopControlMaskNone = 0, - SpvLoopControlUnrollMask = 0x00000001, - SpvLoopControlDontUnrollMask = 0x00000002, -} SpvLoopControlMask; - -typedef enum SpvFunctionControlShift_ { - SpvFunctionControlInlineShift = 0, - SpvFunctionControlDontInlineShift = 1, - SpvFunctionControlPureShift = 2, - SpvFunctionControlConstShift = 3, -} 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, -} 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, -} SpvMemorySemanticsMask; - -typedef enum SpvMemoryAccessShift_ { - SpvMemoryAccessVolatileShift = 0, - SpvMemoryAccessAlignedShift = 1, - SpvMemoryAccessNontemporalShift = 2, -} SpvMemoryAccessShift; - -typedef enum SpvMemoryAccessMask_ { - SpvMemoryAccessMaskNone = 0, - SpvMemoryAccessVolatileMask = 0x00000001, - SpvMemoryAccessAlignedMask = 0x00000002, - SpvMemoryAccessNontemporalMask = 0x00000004, -} SpvMemoryAccessMask; - -typedef enum SpvScope_ { - SpvScopeCrossDevice = 0, - SpvScopeDevice = 1, - SpvScopeWorkgroup = 2, - SpvScopeSubgroup = 3, - SpvScopeInvocation = 4, -} SpvScope; - -typedef enum SpvGroupOperation_ { - SpvGroupOperationReduce = 0, - SpvGroupOperationInclusiveScan = 1, - SpvGroupOperationExclusiveScan = 2, -} SpvGroupOperation; - -typedef enum SpvKernelEnqueueFlags_ { - SpvKernelEnqueueFlagsNoWait = 0, - SpvKernelEnqueueFlagsWaitKernel = 1, - SpvKernelEnqueueFlagsWaitWorkGroup = 2, -} SpvKernelEnqueueFlags; - -typedef enum SpvKernelProfilingInfoShift_ { - SpvKernelProfilingInfoCmdExecTimeShift = 0, -} 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, -} SpvCapability; - -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, -} SpvOp; - -#endif // #ifndef spirv_H - diff --git a/third_party/spirv/spirv.hpp11 b/third_party/spirv/spirv.hpp11 deleted file mode 100644 index 03faaac38..000000000 --- a/third_party/spirv/spirv.hpp11 +++ /dev/null @@ -1,880 +0,0 @@ -// Copyright (c) 2014-2016 The Khronos Group Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and/or associated documentation files (the "Materials"), -// to deal in the Materials without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Materials, and to permit persons to whom the -// Materials are furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Materials. -// -// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -// -// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -// IN THE MATERIALS. - -// 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 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'] -// -// 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 0x10000 -#define SPV_REVISION 3 - -static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010000; -static const unsigned int Revision = 3; -static const unsigned int OpCodeMask = 0xffff; -static const unsigned int WordCountShift = 16; - -enum class SourceLanguage : unsigned { - Unknown = 0, - ESSL = 1, - GLSL = 2, - OpenCL_C = 3, - OpenCL_CPP = 4, -}; - -enum class ExecutionModel : unsigned { - Vertex = 0, - TessellationControl = 1, - TessellationEvaluation = 2, - Geometry = 3, - Fragment = 4, - GLCompute = 5, - Kernel = 6, -}; - -enum class AddressingModel : unsigned { - Logical = 0, - Physical32 = 1, - Physical64 = 2, -}; - -enum class MemoryModel : unsigned { - Simple = 0, - GLSL450 = 1, - OpenCL = 2, -}; - -enum class ExecutionMode : unsigned { - Invocations = 0, - SpacingEqual = 1, - SpacingFractionalEven = 2, - SpacingFractionalOdd = 3, - VertexOrderCw = 4, - VertexOrderCcw = 5, - PixelCenterInteger = 6, - OriginUpperLeft = 7, - OriginLowerLeft = 8, - EarlyFragmentTests = 9, - PointMode = 10, - Xfb = 11, - DepthReplacing = 12, - DepthGreater = 14, - DepthLess = 15, - DepthUnchanged = 16, - LocalSize = 17, - LocalSizeHint = 18, - InputPoints = 19, - InputLines = 20, - InputLinesAdjacency = 21, - Triangles = 22, - InputTrianglesAdjacency = 23, - Quads = 24, - Isolines = 25, - OutputVertices = 26, - OutputPoints = 27, - OutputLineStrip = 28, - OutputTriangleStrip = 29, - VecTypeHint = 30, - ContractionOff = 31, -}; - -enum class StorageClass : unsigned { - UniformConstant = 0, - Input = 1, - Uniform = 2, - Output = 3, - Workgroup = 4, - CrossWorkgroup = 5, - Private = 6, - Function = 7, - Generic = 8, - PushConstant = 9, - AtomicCounter = 10, - Image = 11, -}; - -enum class Dim : unsigned { - Dim1D = 0, - Dim2D = 1, - Dim3D = 2, - Cube = 3, - Rect = 4, - Buffer = 5, - SubpassData = 6, -}; - -enum class SamplerAddressingMode : unsigned { - None = 0, - ClampToEdge = 1, - Clamp = 2, - Repeat = 3, - RepeatMirrored = 4, -}; - -enum class SamplerFilterMode : unsigned { - Nearest = 0, - Linear = 1, -}; - -enum class ImageFormat : unsigned { - Unknown = 0, - Rgba32f = 1, - Rgba16f = 2, - R32f = 3, - Rgba8 = 4, - Rgba8Snorm = 5, - Rg32f = 6, - Rg16f = 7, - R11fG11fB10f = 8, - R16f = 9, - Rgba16 = 10, - Rgb10A2 = 11, - Rg16 = 12, - Rg8 = 13, - R16 = 14, - R8 = 15, - Rgba16Snorm = 16, - Rg16Snorm = 17, - Rg8Snorm = 18, - R16Snorm = 19, - R8Snorm = 20, - Rgba32i = 21, - Rgba16i = 22, - Rgba8i = 23, - R32i = 24, - Rg32i = 25, - Rg16i = 26, - Rg8i = 27, - R16i = 28, - R8i = 29, - Rgba32ui = 30, - Rgba16ui = 31, - Rgba8ui = 32, - R32ui = 33, - Rgb10a2ui = 34, - Rg32ui = 35, - Rg16ui = 36, - Rg8ui = 37, - R16ui = 38, - R8ui = 39, -}; - -enum class ImageChannelOrder : unsigned { - R = 0, - A = 1, - RG = 2, - RA = 3, - RGB = 4, - RGBA = 5, - BGRA = 6, - ARGB = 7, - Intensity = 8, - Luminance = 9, - Rx = 10, - RGx = 11, - RGBx = 12, - Depth = 13, - DepthStencil = 14, - sRGB = 15, - sRGBx = 16, - sRGBA = 17, - sBGRA = 18, -}; - -enum class ImageChannelDataType : unsigned { - SnormInt8 = 0, - SnormInt16 = 1, - UnormInt8 = 2, - UnormInt16 = 3, - UnormShort565 = 4, - UnormShort555 = 5, - UnormInt101010 = 6, - SignedInt8 = 7, - SignedInt16 = 8, - SignedInt32 = 9, - UnsignedInt8 = 10, - UnsignedInt16 = 11, - UnsignedInt32 = 12, - HalfFloat = 13, - Float = 14, - UnormInt24 = 15, - UnormInt101010_2 = 16, -}; - -enum class ImageOperandsShift : unsigned { - Bias = 0, - Lod = 1, - Grad = 2, - ConstOffset = 3, - Offset = 4, - ConstOffsets = 5, - Sample = 6, - MinLod = 7, -}; - -enum class ImageOperandsMask : unsigned { - MaskNone = 0, - Bias = 0x00000001, - Lod = 0x00000002, - Grad = 0x00000004, - ConstOffset = 0x00000008, - Offset = 0x00000010, - ConstOffsets = 0x00000020, - Sample = 0x00000040, - MinLod = 0x00000080, -}; - -enum class FPFastMathModeShift : unsigned { - NotNaN = 0, - NotInf = 1, - NSZ = 2, - AllowRecip = 3, - Fast = 4, -}; - -enum class FPFastMathModeMask : unsigned { - MaskNone = 0, - NotNaN = 0x00000001, - NotInf = 0x00000002, - NSZ = 0x00000004, - AllowRecip = 0x00000008, - Fast = 0x00000010, -}; - -enum class FPRoundingMode : unsigned { - RTE = 0, - RTZ = 1, - RTP = 2, - RTN = 3, -}; - -enum class LinkageType : unsigned { - Export = 0, - Import = 1, -}; - -enum class AccessQualifier : unsigned { - ReadOnly = 0, - WriteOnly = 1, - ReadWrite = 2, -}; - -enum class FunctionParameterAttribute : unsigned { - Zext = 0, - Sext = 1, - ByVal = 2, - Sret = 3, - NoAlias = 4, - NoCapture = 5, - NoWrite = 6, - NoReadWrite = 7, -}; - -enum class Decoration : unsigned { - RelaxedPrecision = 0, - SpecId = 1, - Block = 2, - BufferBlock = 3, - RowMajor = 4, - ColMajor = 5, - ArrayStride = 6, - MatrixStride = 7, - GLSLShared = 8, - GLSLPacked = 9, - CPacked = 10, - BuiltIn = 11, - NoPerspective = 13, - Flat = 14, - Patch = 15, - Centroid = 16, - Sample = 17, - Invariant = 18, - Restrict = 19, - Aliased = 20, - Volatile = 21, - Constant = 22, - Coherent = 23, - NonWritable = 24, - NonReadable = 25, - Uniform = 26, - SaturatedConversion = 28, - Stream = 29, - Location = 30, - Component = 31, - Index = 32, - Binding = 33, - DescriptorSet = 34, - Offset = 35, - XfbBuffer = 36, - XfbStride = 37, - FuncParamAttr = 38, - FPRoundingMode = 39, - FPFastMathMode = 40, - LinkageAttributes = 41, - NoContraction = 42, - InputAttachmentIndex = 43, - Alignment = 44, -}; - -enum class BuiltIn : unsigned { - Position = 0, - PointSize = 1, - ClipDistance = 3, - CullDistance = 4, - VertexId = 5, - InstanceId = 6, - PrimitiveId = 7, - InvocationId = 8, - Layer = 9, - ViewportIndex = 10, - TessLevelOuter = 11, - TessLevelInner = 12, - TessCoord = 13, - PatchVertices = 14, - FragCoord = 15, - PointCoord = 16, - FrontFacing = 17, - SampleId = 18, - SamplePosition = 19, - SampleMask = 20, - FragDepth = 22, - HelperInvocation = 23, - NumWorkgroups = 24, - WorkgroupSize = 25, - WorkgroupId = 26, - LocalInvocationId = 27, - GlobalInvocationId = 28, - LocalInvocationIndex = 29, - WorkDim = 30, - GlobalSize = 31, - EnqueuedWorkgroupSize = 32, - GlobalOffset = 33, - GlobalLinearId = 34, - SubgroupSize = 36, - SubgroupMaxSize = 37, - NumSubgroups = 38, - NumEnqueuedSubgroups = 39, - SubgroupId = 40, - SubgroupLocalInvocationId = 41, - VertexIndex = 42, - InstanceIndex = 43, -}; - -enum class SelectionControlShift : unsigned { - Flatten = 0, - DontFlatten = 1, -}; - -enum class SelectionControlMask : unsigned { - MaskNone = 0, - Flatten = 0x00000001, - DontFlatten = 0x00000002, -}; - -enum class LoopControlShift : unsigned { - Unroll = 0, - DontUnroll = 1, -}; - -enum class LoopControlMask : unsigned { - MaskNone = 0, - Unroll = 0x00000001, - DontUnroll = 0x00000002, -}; - -enum class FunctionControlShift : unsigned { - Inline = 0, - DontInline = 1, - Pure = 2, - Const = 3, -}; - -enum class FunctionControlMask : unsigned { - MaskNone = 0, - Inline = 0x00000001, - DontInline = 0x00000002, - Pure = 0x00000004, - Const = 0x00000008, -}; - -enum class MemorySemanticsShift : unsigned { - Acquire = 1, - Release = 2, - AcquireRelease = 3, - SequentiallyConsistent = 4, - UniformMemory = 6, - SubgroupMemory = 7, - WorkgroupMemory = 8, - CrossWorkgroupMemory = 9, - AtomicCounterMemory = 10, - ImageMemory = 11, -}; - -enum class MemorySemanticsMask : unsigned { - MaskNone = 0, - Acquire = 0x00000002, - Release = 0x00000004, - AcquireRelease = 0x00000008, - SequentiallyConsistent = 0x00000010, - UniformMemory = 0x00000040, - SubgroupMemory = 0x00000080, - WorkgroupMemory = 0x00000100, - CrossWorkgroupMemory = 0x00000200, - AtomicCounterMemory = 0x00000400, - ImageMemory = 0x00000800, -}; - -enum class MemoryAccessShift : unsigned { - Volatile = 0, - Aligned = 1, - Nontemporal = 2, -}; - -enum class MemoryAccessMask : unsigned { - MaskNone = 0, - Volatile = 0x00000001, - Aligned = 0x00000002, - Nontemporal = 0x00000004, -}; - -enum class Scope : unsigned { - CrossDevice = 0, - Device = 1, - Workgroup = 2, - Subgroup = 3, - Invocation = 4, -}; - -enum class GroupOperation : unsigned { - Reduce = 0, - InclusiveScan = 1, - ExclusiveScan = 2, -}; - -enum class KernelEnqueueFlags : unsigned { - NoWait = 0, - WaitKernel = 1, - WaitWorkGroup = 2, -}; - -enum class KernelProfilingInfoShift : unsigned { - CmdExecTime = 0, -}; - -enum class KernelProfilingInfoMask : unsigned { - MaskNone = 0, - CmdExecTime = 0x00000001, -}; - -enum class Capability : unsigned { - Matrix = 0, - Shader = 1, - Geometry = 2, - Tessellation = 3, - Addresses = 4, - Linkage = 5, - Kernel = 6, - Vector16 = 7, - Float16Buffer = 8, - Float16 = 9, - Float64 = 10, - Int64 = 11, - Int64Atomics = 12, - ImageBasic = 13, - ImageReadWrite = 14, - ImageMipmap = 15, - Pipes = 17, - Groups = 18, - DeviceEnqueue = 19, - LiteralSampler = 20, - AtomicStorage = 21, - Int16 = 22, - TessellationPointSize = 23, - GeometryPointSize = 24, - ImageGatherExtended = 25, - StorageImageMultisample = 27, - UniformBufferArrayDynamicIndexing = 28, - SampledImageArrayDynamicIndexing = 29, - StorageBufferArrayDynamicIndexing = 30, - StorageImageArrayDynamicIndexing = 31, - ClipDistance = 32, - CullDistance = 33, - ImageCubeArray = 34, - SampleRateShading = 35, - ImageRect = 36, - SampledRect = 37, - GenericPointer = 38, - Int8 = 39, - InputAttachment = 40, - SparseResidency = 41, - MinLod = 42, - Sampled1D = 43, - Image1D = 44, - SampledCubeArray = 45, - SampledBuffer = 46, - ImageBuffer = 47, - ImageMSArray = 48, - StorageImageExtendedFormats = 49, - ImageQuery = 50, - DerivativeControl = 51, - InterpolationFunction = 52, - TransformFeedback = 53, - GeometryStreams = 54, - StorageImageReadWithoutFormat = 55, - StorageImageWriteWithoutFormat = 56, - MultiViewport = 57, -}; - -enum class Op : unsigned { - 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, -}; - -// 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)); } - -} // end namespace spv - -#endif // #ifndef spirv_HPP -